home *** CD-ROM | disk | FTP | other *** search
/ Aminet 4 / Aminet 4 - November 1994.iso / aminet / comm / term / term41source.lha / Extras / Source / term-Source.lha / termAux.c < prev    next >
C/C++ Source or Header  |  1994-08-18  |  74KB  |  4,006 lines

  1. /*
  2. **    termAux.c
  3. **
  4. **    Miscellaneous support routines
  5. **
  6. **    Copyright © 1990-1994 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* This variable stores the current state of the
  13.      * dialing menu items.
  14.      */
  15.  
  16. STATIC BYTE DialItemsAvailable = TRUE;
  17.  
  18.     /* Current timer state. */
  19.  
  20. STATIC BYTE TimerRunning = FALSE;
  21.  
  22.     /* StripSpaces(STRPTR String):
  23.      *
  24.      *    Strip leading and trailing spaces from a string.
  25.      */
  26.  
  27. VOID __regargs
  28. StripSpaces(STRPTR String)
  29. {
  30.     if(String)
  31.     {
  32.         STRPTR    To = String;
  33.         WORD    Len;
  34.  
  35.         while(*String == ' ')
  36.             String++;
  37.  
  38.         if(Len = strlen(String))
  39.         {
  40.             while(Len > 0 && String[Len - 1] == ' ')
  41.                 Len--;
  42.  
  43.             while(Len--)
  44.                 *To++ = *String++;
  45.         }
  46.  
  47.         *To = 0;
  48.     }
  49. }
  50.  
  51.     /* ReplaceWindowInfo(struct WindowInfo *NewInfo):
  52.      *
  53.      *    Drop the window info into the right place.
  54.      */
  55.  
  56. VOID __regargs
  57. ReplaceWindowInfo(struct WindowInfo *NewInfo)
  58. {
  59.     WORD i;
  60.  
  61.     for(i = 0 ; i < WINDOW_COUNT ; i++)
  62.     {
  63.         if(WindowInfoTable[i] . ID == NewInfo -> ID)
  64.         {
  65.             CopyMem(NewInfo,&WindowInfoTable[i],sizeof(struct WindowInfo));
  66.  
  67.             break;
  68.         }
  69.     }
  70. }
  71.  
  72.     /* PutWindowInfo():
  73.      *
  74.      *    Store window size and position relative to
  75.      *    the main window.
  76.      */
  77.  
  78. VOID __regargs
  79. PutWindowInfo(UBYTE ID,LONG Left,LONG Top,LONG Width,LONG Height)
  80. {
  81.     struct WindowInfo    *Info;
  82.     WORD             i;
  83.     LONG             WindowLeft,
  84.                  WindowTop,
  85.                  WindowWidth,
  86.                  WindowHeight;
  87.     ULONG             IntuiLock;
  88.  
  89.     for(i = 0 ; i < WINDOW_COUNT ; i++)
  90.     {
  91.         if(WindowInfoTable[i] . ID == ID)
  92.         {
  93.             Info = &WindowInfoTable[i];
  94.  
  95.             break;
  96.         }
  97.     }
  98.  
  99.     IntuiLock = LockIBase(NULL);
  100.  
  101.     WindowLeft    = Window -> LeftEdge;
  102.     WindowTop    = Window -> TopEdge;
  103.     WindowWidth    = Window -> Width;
  104.     WindowHeight    = Window -> Height;
  105.  
  106.     UnlockIBase(IntuiLock);
  107.  
  108.     Forbid();
  109.  
  110.     Info -> WindowFlags = NULL;
  111.  
  112.     if(WindowWidth == Width && WindowLeft == Left)
  113.         Info -> WindowFlags |= WC_EXPANDWIDTH;
  114.     else
  115.     {
  116.         if(Left == WindowLeft + WindowWidth)
  117.             Info -> WindowFlags |= WC_ALIGNSIDE;
  118.  
  119.         if(WindowLeft == Left)
  120.             Info -> WindowFlags |= WC_ALIGNLEFT;
  121.  
  122.         if(WindowLeft + WindowWidth == Left + Width)
  123.             Info -> WindowFlags |= WC_ALIGNRIGHT;
  124.     }
  125.  
  126.     if(WindowHeight == Height && WindowTop == Top)
  127.         Info -> WindowFlags |= WC_EXPANDHEIGHT;
  128.     else
  129.     {
  130.         if(Top == WindowTop + WindowHeight)
  131.             Info -> WindowFlags |= WC_ALIGNBELOW;
  132.  
  133.         if(WindowTop == Top)
  134.             Info -> WindowFlags |= WC_ALIGNTOP;
  135.  
  136.         if(WindowTop + WindowHeight == Top + Height)
  137.             Info -> WindowFlags |= WC_ALIGNBOTTOM;
  138.     }
  139.  
  140.     Info -> Left    = Left;
  141.     Info -> Top    = Top;
  142.     Info -> Width    = Width;
  143.     Info -> Height    = Height;
  144.  
  145.     Permit();
  146. }
  147.  
  148.     /* GetWindowInfo():
  149.      *
  150.      *    Set the window size and position in relation to
  151.      *    the main window.
  152.      */
  153.  
  154. VOID __regargs
  155. GetWindowInfo(UBYTE ID,LONG *Left,LONG *Top,LONG *Width,LONG *Height,LONG DefWidth,LONG DefHeight)
  156. {
  157.     struct WindowInfo    *Info;
  158.     WORD             i;
  159.     LONG             WindowLeft,
  160.                  WindowTop,
  161.                  WindowWidth,
  162.                  WindowHeight;
  163.     ULONG             IntuiLock;
  164.  
  165.     if(DefWidth && DefWidth < Window -> Width / 2)
  166.         DefWidth = Window -> Width / 2;
  167.  
  168.     if(DefHeight && DefHeight < Window -> Height / 2)
  169.         DefHeight = Window -> Height / 2;
  170.  
  171.     for(i = 0 ; i < WINDOW_COUNT ; i++)
  172.     {
  173.         if(WindowInfoTable[i] . ID == ID)
  174.         {
  175.             Info = &WindowInfoTable[i];
  176.  
  177.             break;
  178.         }
  179.     }
  180.  
  181.     IntuiLock = LockIBase(NULL);
  182.  
  183.     WindowLeft    = Window -> LeftEdge;
  184.     WindowTop    = Window -> TopEdge;
  185.     WindowWidth    = Window -> Width;
  186.     WindowHeight    = Window -> Height;
  187.  
  188.     UnlockIBase(IntuiLock);
  189.  
  190.     Forbid();
  191.  
  192.     if(*Width)
  193.     {
  194.         if(Info -> Width)
  195.             *Left = Info -> Left;
  196.         else
  197.             *Left = WindowLeft + (WindowWidth - *Width) / 2;
  198.     }
  199.     else
  200.     {
  201.         if(DefWidth && !Info -> Width)
  202.         {
  203.             *Width    = DefWidth;
  204.             *Left    = WindowLeft + (WindowWidth - *Width) / 2;
  205.         }
  206.         else
  207.         {
  208.             if(Info -> Width)
  209.             {
  210.                 *Width    = Info -> Width;
  211.                 *Left    = Info -> Left;
  212.             }
  213.             else
  214.             {
  215. /*                *Width    = WindowWidth / 2;*/
  216. /*                *Left    = WindowLeft + WindowWidth / 4;*/
  217.  
  218.                 *Width    = WindowWidth;
  219.                 *Left    = WindowLeft;
  220.             }
  221.         }
  222.     }
  223.  
  224.     if(*Height)
  225.     {
  226.         if(Info -> Height)
  227.             *Top = Info -> Top;
  228.         else
  229.             *Top = WindowTop + (WindowHeight - *Height) / 2;
  230.     }
  231.     else
  232.     {
  233.         if(DefHeight && !Info -> Height)
  234.         {
  235.             *Height    = DefHeight;
  236.             *Top    = WindowTop + (WindowHeight - *Height) / 2;
  237.         }
  238.         else
  239.         {
  240.             if(Info -> Height)
  241.             {
  242.                 *Height    = Info -> Height;
  243.                 *Top    = Info -> Top;
  244.             }
  245.             else
  246.             {
  247. /*                *Height    = WindowHeight / 2;*/
  248. /*                *Top    = WindowTop + WindowHeight / 4;*/
  249.  
  250.                 *Height    = WindowHeight;
  251.                 *Top    = WindowTop;
  252.             }
  253.         }
  254.     }
  255.  
  256.     if(Info -> WindowFlags & WC_ALIGNSIDE)
  257.         *Left = WindowLeft + WindowWidth;
  258.  
  259.     if(Info -> WindowFlags & WC_ALIGNBELOW)
  260.         *Top = WindowTop + WindowHeight;
  261.  
  262.     if(Info -> WindowFlags & WC_ALIGNLEFT)
  263.         *Left = WindowLeft;
  264.  
  265.     if(Info -> WindowFlags & WC_ALIGNTOP)
  266.         *Top = WindowTop;
  267.  
  268.     if(Info -> WindowFlags & WC_ALIGNRIGHT)
  269.         *Left = WindowLeft + WindowWidth - *Width;
  270.  
  271.     if(Info -> WindowFlags & WC_ALIGNBOTTOM)
  272.         *Top = WindowTop + WindowHeight - *Height;
  273.  
  274.     if(Info -> WindowFlags & WC_EXPANDWIDTH)
  275.         *Width = WindowWidth;
  276.  
  277.     if(Info -> WindowFlags & WC_EXPANDHEIGHT)
  278.         *Height = WindowHeight;
  279.  
  280.     Permit();
  281. }
  282.  
  283.     /* GetDPI(ULONG Mode,ULONG *X_DPI,ULONG *Y_DPI):
  284.      *
  285.      *    Get screen DPI resolution values.
  286.      */
  287.  
  288. VOID __regargs
  289. GetDPI(ULONG Mode,ULONG *X_DPI,ULONG *Y_DPI)
  290. {
  291.     struct DisplayInfo DisplayInfo;
  292.  
  293.     if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,Mode))
  294.     {
  295.         *X_DPI = (35 * 140) / DisplayInfo . PixelSpeed;
  296.         *Y_DPI = (*X_DPI * DisplayInfo . Resolution . x) / DisplayInfo . Resolution . y;
  297.     }
  298.     else
  299.         *X_DPI = *Y_DPI = 72;
  300. }
  301.  
  302.     /* AddProtection(STRPTR FileName,ULONG Mask):
  303.      *
  304.      *    Set bits in the protection mask of a file.
  305.      */
  306.  
  307. VOID __regargs
  308. AddProtection(STRPTR Name,ULONG Mask)
  309. {
  310.     struct FileInfoBlock *FileInfo;
  311.  
  312.     if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  313.     {
  314.         BPTR FileLock;
  315.  
  316.         if(FileLock = Lock(Name,ACCESS_READ))
  317.         {
  318.             if(Examine(FileLock,FileInfo))
  319.             {
  320.                 UnLock(FileLock);
  321.  
  322.                 SetProtection(Name,FileInfo -> fib_Protection | Mask);
  323.             }
  324.             else
  325.                 UnLock(FileLock);
  326.         }
  327.  
  328.         FreeDosObject(DOS_FIB,FileInfo);
  329.     }
  330. }
  331.  
  332.     /* GetPubScreenName(struct Screen *Screen,STRPTR Name):
  333.      *
  334.      *    Get the name of a public screen.
  335.      */
  336.  
  337. BYTE __regargs
  338. GetPubScreenName(struct Screen *Screen,STRPTR Name)
  339. {
  340.     struct List        *PubScreenList;
  341.     struct PubScreenNode    *ScreenNode;
  342.  
  343.     PubScreenList = LockPubScreenList();
  344.  
  345.     for(ScreenNode = (struct PubScreenNode *)PubScreenList -> lh_Head ; ScreenNode -> psn_Node . ln_Succ ; ScreenNode = (struct PubScreenNode *)ScreenNode -> psn_Node . ln_Succ)
  346.     {
  347.         if(ScreenNode -> psn_Screen == Screen)
  348.         {
  349.             strcpy(Name,ScreenNode -> psn_Node . ln_Name);
  350.  
  351.             UnlockPubScreenList();
  352.  
  353.             return(TRUE);
  354.         }
  355.     }
  356.  
  357.     UnlockPubScreenList();
  358.  
  359.     return(FALSE);
  360. }
  361.  
  362.     /* InitSinglePort(struct MsgPort *Port):
  363.      *
  364.      *    Initialize a plain MsgPort (as created on the stack) for
  365.      *    usage. Don't try this at home, kids!
  366.      */
  367.  
  368. VOID __regargs
  369. InitSinglePort(struct MsgPort *Port)
  370. {
  371.     memset(Port,0,sizeof(struct MsgPort));
  372.  
  373.     Port -> mp_Flags    = PA_SIGNAL;
  374.     Port -> mp_SigBit    = SIGB_SINGLE;
  375.     Port -> mp_SigTask    = SysBase -> ThisTask;
  376.  
  377.     NewList(&Port -> mp_MsgList);
  378. }
  379.  
  380.     /* GoodStream(BPTR Stream):
  381.      *
  382.      *    Check to see whether the current input file
  383.      *    is an interactive stream.
  384.      */
  385.  
  386. BYTE __regargs
  387. GoodStream(BPTR Stream)
  388. {
  389.     if(!Stream)
  390.     {
  391.         struct Process *ThisProcess = (struct Process *)SysBase -> ThisTask;
  392.  
  393.         Stream = ThisProcess -> pr_CIS;
  394.     }
  395.  
  396.     if(Stream)
  397.     {
  398.         struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
  399.  
  400.         if(Handle -> fh_Type)
  401.         {
  402.             if(IsInteractive(Stream))
  403.                 return(TRUE);
  404.         }
  405.     }
  406.  
  407.     return(FALSE);
  408. }
  409.  
  410.     /* GetProgramIcon():
  411.      *
  412.      *    Try to find the icon of the program.
  413.      */
  414.  
  415. struct DiskObject *
  416. GetProgramIcon()
  417. {
  418.     struct DiskObject *Icon = NULL;
  419.  
  420.         /* Run from Workbench? */
  421.  
  422.     if(WBenchMsg)
  423.     {
  424.             /* Sanity check. */
  425.  
  426.         if(WBenchMsg -> sm_ArgList)
  427.         {
  428.                 /* Yet another sanity check. */
  429.  
  430.             if(WBenchMsg -> sm_ArgList -> wa_Name)
  431.             {
  432.                     /* Try to find the icon in the current directory. */
  433.  
  434.                 if(Icon = GetDiskObjectNew(WBenchMsg -> sm_ArgList -> wa_Name))
  435.                 {
  436.                     if(Icon -> do_Type != WBTOOL)
  437.                     {
  438.                         FreeDiskObject(Icon);
  439.  
  440.                         Icon = NULL;
  441.                     }
  442.                 }
  443.  
  444.                 if(!Icon)
  445.                 {
  446.                     BPTR NewLock;
  447.  
  448.                         /* Move to the directory the
  449.                          * program was run from.
  450.                          */
  451.  
  452.                     if(NewLock = Lock("PROGDIR:",ACCESS_READ))
  453.                     {
  454.                         BPTR OldLock;
  455.  
  456.                         OldLock = CurrentDir(NewLock);
  457.  
  458.                             /* Try to fetch the icon, use the
  459.                              * default name if necessary.
  460.                              */
  461.  
  462.                         if(Icon = GetDiskObjectNew(WBenchMsg -> sm_ArgList -> wa_Name))
  463.                         {
  464.                             if(Icon -> do_Type != WBTOOL)
  465.                             {
  466.                                 FreeDiskObject(Icon);
  467.  
  468.                                 Icon = NULL;
  469.                             }
  470.                         }
  471.  
  472.                         if(!Icon)
  473.                         {
  474.                             if(Icon = GetDiskObjectNew("term"))
  475.                             {
  476.                                 if(Icon -> do_Type != WBTOOL)
  477.                                 {
  478.                                     FreeDiskObject(Icon);
  479.  
  480.                                     Icon = NULL;
  481.                                 }
  482.                             }
  483.                         }
  484.  
  485.                         CurrentDir(OldLock);
  486.  
  487.                         UnLock(NewLock);
  488.                     }
  489.                 }
  490.             }
  491.         }
  492.     }
  493.  
  494.         /* Still no success. */
  495.  
  496.     if(!Icon)
  497.     {
  498.             /* Use the default names. */
  499.  
  500.         if(Icon = GetDiskObjectNew("term"))
  501.         {
  502.             if(Icon -> do_Type != WBTOOL)
  503.             {
  504.                 FreeDiskObject(Icon);
  505.  
  506.                 Icon = NULL;
  507.             }
  508.         }
  509.  
  510.         if(!Icon)
  511.         {
  512.             if(Icon = GetDiskObjectNew("PROGDIR:term"))
  513.             {
  514.                 if(Icon -> do_Type != WBTOOL)
  515.                 {
  516.                     FreeDiskObject(Icon);
  517.  
  518.                     Icon = NULL;
  519.                 }
  520.             }
  521.         }
  522.     }
  523.  
  524.     return(Icon);
  525. }
  526.  
  527.     /* GetPenIndex(LONG Pen):
  528.      *
  529.      *    Get the table index corresponding to an on-screen
  530.      *    text rendering pen.
  531.      */
  532.  
  533. LONG __regargs
  534. GetPenIndex(LONG Pen)
  535. {
  536.     LONG i;
  537.  
  538.     for(i = 0 ; i < 16 ; i++)
  539.     {
  540.         if(MappedPens[0][i] == Pen)
  541.             return(i);
  542.     }
  543. }
  544.  
  545.     /* GetScreenWidth(struct Window *Window):
  546.      *
  547.      *    Query the current screen width.
  548.      */
  549.  
  550. LONG __regargs
  551. GetScreenWidth(struct Window *Window)
  552. {
  553.     if(Window)
  554.     {
  555.         if(Window -> Width > ScreenWidth || Window -> LeftEdge < -Window -> WScreen -> LeftEdge || Window -> LeftEdge + Window -> WScreen -> LeftEdge + Window -> Width > ScreenWidth)
  556.             return(ScreenWidth);
  557.         else
  558.             return(Window -> Width - (Window -> BorderLeft + Window -> BorderRight));
  559.     }
  560.     else
  561.         return(ScreenWidth);
  562. }
  563.  
  564.     /* GetScreenHeight(struct Window *Window):
  565.      *
  566.      *    Query the current screen height.
  567.      */
  568.  
  569. LONG __regargs
  570. GetScreenHeight(struct Window *Window)
  571. {
  572.     if(Window)
  573.     {
  574.         if(Window -> Height > ScreenHeight || Window -> TopEdge < -Window -> WScreen -> TopEdge || Window -> TopEdge + Window -> WScreen -> TopEdge + Window -> Height > ScreenHeight)
  575.             return(ScreenHeight);
  576.         else
  577.             return(Window -> Height - (Window -> BorderTop + Window -> BorderBottom));
  578.     }
  579.     else
  580.         return(ScreenHeight);
  581. }
  582.  
  583.     /* GetLeft(struct Screen *Screen):
  584.      *
  585.      *    Get the screen left edge.
  586.      */
  587.  
  588. STATIC LONG __regargs
  589. GetLeft(struct Screen *Screen)
  590. {
  591.     if(Screen -> LeftEdge >= 0)
  592.         return(0);
  593.     else
  594.         return(-Screen -> LeftEdge);
  595. }
  596.  
  597.     /* GetScreenLeft(struct Window *Window):
  598.      *
  599.      *    Query the current screen left edge.
  600.      */
  601.  
  602. LONG __regargs
  603. GetScreenLeft(struct Window *Window)
  604. {
  605.     if(Window)
  606.     {
  607.         if(Window -> Width > ScreenWidth || Window -> LeftEdge < -Window -> WScreen -> LeftEdge || Window -> LeftEdge + Window -> WScreen -> LeftEdge + Window -> Width > ScreenWidth)
  608.             return(GetLeft(Window -> WScreen));
  609.         else
  610.             return(Window -> LeftEdge + Window -> BorderLeft);
  611.     }
  612.     else
  613.         return(GetLeft(DefaultPubScreen ? DefaultPubScreen : SharedScreen));
  614. }
  615.  
  616.     /* GetTop(struct Screen *Screen):
  617.      *
  618.      *    Get the screen top edge.
  619.      */
  620.  
  621. STATIC LONG __regargs
  622. GetTop(struct Screen *Screen)
  623. {
  624.     if(Screen -> TopEdge >= 0)
  625.         return(0);
  626.     else
  627.         return(-Screen -> TopEdge);
  628. }
  629.  
  630.     /* GetScreenTop(struct Window *Window):
  631.      *
  632.      *    Query the current screen top edge.
  633.      */
  634.  
  635. LONG __regargs
  636. GetScreenTop(struct Window *Window)
  637. {
  638.     if(Window)
  639.     {
  640.         if(Window -> Height > ScreenHeight || Window -> TopEdge < -Window -> WScreen -> TopEdge || Window -> TopEdge + Window -> WScreen -> TopEdge + Window -> Height > ScreenHeight)
  641.             return(GetTop(Window -> WScreen));
  642.         else
  643.             return(Window -> TopEdge + Window -> BorderTop);
  644.     }
  645.     else
  646.         return(GetTop(DefaultPubScreen ? DefaultPubScreen : SharedScreen));
  647. }
  648.  
  649.     /* OldGetAPen(struct RastPort *RPort):
  650.      *
  651.      *    Query the current primary rendering colour (old style).
  652.      */
  653.  
  654. ULONG 
  655. OldGetAPen(struct RastPort *RPort)
  656. {
  657.     return((ULONG)RPort -> FgPen);
  658. }
  659.  
  660.     /* OldGetBPen(struct RastPort *RPort):
  661.      *
  662.      *    Query the current seconary rendering colour (old style).
  663.      */
  664.  
  665. ULONG 
  666. OldGetBPen(struct RastPort *RPort)
  667. {
  668.     return((ULONG)RPort -> BgPen);
  669. }
  670.  
  671.     /* OldGetDrMd(struct RastPort *RPort):
  672.      *
  673.      *    Query the current drawing mode (old style).
  674.      */
  675.  
  676. ULONG 
  677. OldGetDrMd(struct RastPort *RPort)
  678. {
  679.     return((ULONG)RPort -> DrawMode);
  680. }
  681.  
  682.     /* OldSetWrMsk(struct RastPort *RPort,ULONG Mask):
  683.      *
  684.      *    Set the rendering plane mask (old style).
  685.      */
  686.  
  687. ULONG 
  688. OldSetWrMsk(struct RastPort *RPort,ULONG Mask)
  689. {
  690.     RPort -> Mask = Mask;
  691.  
  692.     return((ULONG)1);
  693. }
  694.  
  695.     /* NewGetAPen(struct RastPort *RPort):
  696.      *
  697.      *    Query the current primary rendering colour (new style).
  698.      */
  699.  
  700. ULONG 
  701. NewGetAPen(struct RastPort *RPort)
  702. {
  703.     return(GetAPen(RPort));
  704. }
  705.  
  706.     /* NewGetBPen(struct RastPort *RPort):
  707.      *
  708.      *    Query the current seconary rendering colour (new style).
  709.      */
  710.  
  711. ULONG 
  712. NewGetBPen(struct RastPort *RPort)
  713. {
  714.     return(GetBPen(RPort));
  715. }
  716.  
  717.     /* NewGetDrMd(struct RastPort *RPort):
  718.      *
  719.      *    Query the current drawing mode (new style).
  720.      */
  721.  
  722. ULONG 
  723. NewGetDrMd(struct RastPort *RPort)
  724. {
  725.     return(GetDrMd(RPort));
  726. }
  727.  
  728.     /* NewSetWrMsk(struct RastPort *RPort,ULONG Mask):
  729.      *
  730.      *    Set the rendering plane mask (new style).
  731.      */
  732.  
  733. ULONG 
  734. NewSetWrMsk(struct RastPort *RPort,ULONG Mask)
  735. {
  736.     return(SetWriteMask(RPort,Mask));
  737. }
  738.  
  739.     /* SetWait(struct Window *Window):
  740.      *
  741.      *    Set the busy wait mouse pointer.
  742.      */
  743.  
  744. VOID __regargs
  745. SetWait(struct Window *Window)
  746. {
  747.     if(Kick30)
  748.     {
  749.         SetWindowPointer(Window,
  750.             WA_BusyPointer,        TRUE,
  751.             WA_PointerDelay,    TRUE,
  752.         TAG_DONE);
  753.     }
  754.     else
  755.         SetPointer(Window,Stopwatch,16,16,-6,0);
  756. }
  757.  
  758.     /* ClrWait(struct Window *Window):
  759.      *
  760.      *    Remove the busy wait mouse pointer.
  761.      */
  762.  
  763. VOID __regargs
  764. ClrWait(struct Window *Window)
  765. {
  766.     if(Kick30)
  767.         SetWindowPointer(Window,TAG_DONE);
  768.     else
  769.         ClearPointer(Window);
  770. }
  771.  
  772.     /* GetModeName(ULONG Mode):
  773.      *
  774.      *    Get the name of a display mode.
  775.      */
  776.  
  777. STRPTR __regargs
  778. GetModeName(ULONG Mode)
  779. {
  780.     STATIC UBYTE __far    Buffer[DISPLAYNAMELEN + 1];
  781.     struct NameInfo        NameInfo;
  782.  
  783.     if(GetDisplayInfoData(NULL,(APTR)&NameInfo,sizeof(struct NameInfo),DTAG_NAME,Mode))
  784.         strcpy(Buffer,NameInfo . Name);
  785.     else
  786.     {
  787.         struct DimensionInfo DimensionInfo;
  788.  
  789.         if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,Mode))
  790.         {
  791.             STRPTR MonitorName;
  792.  
  793.             switch(Mode & MONITOR_ID_MASK)
  794.             {
  795.                 case NTSC_MONITOR_ID:
  796.  
  797.                     MonitorName = "NTSC: ";
  798.                     break;
  799.  
  800.                 case PAL_MONITOR_ID:
  801.  
  802.                     MonitorName = "PAL: ";
  803.                     break;
  804.  
  805.                 case VGA_MONITOR_ID:
  806.  
  807.                     MonitorName = "VGA: ";
  808.                     break;
  809.  
  810.                 case A2024_MONITOR_ID:
  811.  
  812.                     MonitorName = "A2024: ";
  813.                     break;
  814.  
  815.                 default:
  816.  
  817.                     MonitorName = "";
  818.                     break;
  819.             }
  820.  
  821.             SPrintf(Buffer,"%s%ld × %ld",MonitorName,DimensionInfo . TxtOScan . MaxX - DimensionInfo . TxtOScan . MinX + 1,DimensionInfo . TxtOScan . MaxY - DimensionInfo . TxtOScan . MinY + 1);
  822.         }
  823.         else
  824.             strcpy(Buffer,LocaleString(MSG_SCREENPANEL_UNKNOWN_TXT));
  825.     }
  826.  
  827.     return(Buffer);
  828. }
  829.  
  830.     /* ModeOkay(ULONG ID):
  831.      *
  832.      *    Checks whether a display mode ID will do for deep
  833.      *    screen bitmaps.
  834.      */
  835.  
  836. BYTE __regargs
  837. ModeOkay(ULONG ID)
  838. {
  839.     struct DimensionInfo DimensionInfo;
  840.  
  841.     if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,ID))
  842.     {
  843.         if(DimensionInfo . MaxDepth >= 4)
  844.             return(TRUE);
  845.     }
  846.  
  847.     return(FALSE);
  848. }
  849.  
  850.     /* SetClipMenu(BYTE Mode):
  851.      *
  852.      *    Enable/disable the copy/clear selection menu items.
  853.      */
  854.  
  855. VOID __regargs
  856. SetClipMenu(BYTE Mode)
  857. {
  858.     if(Mode && RasterEnabled)
  859.     {
  860.         OnItem(MEN_COPY);
  861.         OnItem(MEN_CLEAR);
  862.     }
  863.     else
  864.     {
  865.         OffItem(MEN_COPY);
  866.         OffItem(MEN_CLEAR);
  867.     }
  868. }
  869.  
  870.     /* SetRedialMenu():
  871.      *
  872.      *    Make the `redial' menu item available or make it
  873.      *    unavailable.
  874.      */
  875.  
  876. VOID
  877. SetRedialMenu()
  878. {
  879.     BYTE Mode;
  880.  
  881.     if(DialList)
  882.     {
  883.         if(DialList -> lh_Head -> ln_Succ)
  884.             Mode = TRUE;
  885.         else
  886.             Mode = FALSE;
  887.     }
  888.     else
  889.         Mode = FALSE;
  890.  
  891.     if(Mode && DialItemsAvailable)
  892.         OnItem(MEN_REDIAL);
  893.     else
  894.         OffItem(MEN_REDIAL);
  895. }
  896.  
  897.     /* SetDialMenu(BYTE Mode):
  898.      *
  899.      *    Block or enable the dialing menu.
  900.      */
  901.  
  902. VOID __regargs
  903. SetDialMenu(BYTE Mode)
  904. {
  905.     if(Window && Menu)
  906.     {
  907.         if(Mode)
  908.         {
  909.             if(DialList)
  910.             {
  911.                 if(DialList -> lh_Head -> ln_Succ)
  912.                     OnItem(MEN_REDIAL);
  913.                 else
  914.                     OffItem(MEN_REDIAL);
  915.             }
  916.             else
  917.                 OffItem(MEN_REDIAL);
  918.  
  919.             OnItem(MEN_DIAL_NUMBER);
  920.         }
  921.         else
  922.         {
  923.             OffItem(MEN_REDIAL);
  924.             OffItem(MEN_DIAL_NUMBER);
  925.         }
  926.  
  927.         DialItemsAvailable = Mode;
  928.     }
  929. }
  930.  
  931.     /* SetTransferMenu(BYTE Mode):
  932.      *
  933.      *    Block or enable the transfer menu.
  934.      */
  935.  
  936. VOID __regargs
  937. SetTransferMenu(BYTE Mode)
  938. {
  939.     if(Window && Menu)
  940.     {
  941.         if(Mode)
  942.         {
  943.             ULONG i;
  944.  
  945.             for(i = MEN_UPLOAD_ASCII ; i <= MEN_DOWNLOAD_BINARY ; i++)
  946.                 OnItem(i);
  947.  
  948.             OnItem(MEN_TRANSFER);
  949.         }
  950.         else
  951.         {
  952.             if(!Config -> TransferConfig -> ASCIIUploadLibrary[0])
  953.                 OffItem(MEN_UPLOAD_ASCII);
  954.             else
  955.                 OnItem(MEN_UPLOAD_ASCII);
  956.  
  957.             if(!Config -> TransferConfig -> ASCIIDownloadLibrary[0])
  958.                 OffItem(MEN_DOWNLOAD_ASCII);
  959.             else
  960.                 OnItem(MEN_DOWNLOAD_ASCII);
  961.  
  962.             if(!Config -> TransferConfig -> TextUploadLibrary[0])
  963.             {
  964.                 OffItem(MEN_UPLOAD_TEXT);
  965.                 OffItem(MEN_EDIT_AND_UPLOAD_TEXT);
  966.             }
  967.             else
  968.             {
  969.                 OnItem(MEN_UPLOAD_TEXT);
  970.                 OnItem(MEN_EDIT_AND_UPLOAD_TEXT);
  971.             }
  972.  
  973.             if(!Config -> TransferConfig -> TextDownloadLibrary[0])
  974.                 OffItem(MEN_DOWNLOAD_TEXT);
  975.             else
  976.                 OnItem(MEN_DOWNLOAD_TEXT);
  977.  
  978.             if(!Config -> TransferConfig -> BinaryUploadLibrary[0])
  979.                 OffItem(MEN_UPLOAD_BINARY);
  980.             else
  981.                 OnItem(MEN_UPLOAD_BINARY);
  982.  
  983.             if(!Config -> TransferConfig -> BinaryDownloadLibrary[0])
  984.                 OffItem(MEN_DOWNLOAD_BINARY);
  985.             else
  986.                 OnItem(MEN_DOWNLOAD_BINARY);
  987.  
  988.             OffItem(MEN_TRANSFER);
  989.         }
  990.     }
  991. }
  992.  
  993.     /* SetRasterMenu(BYTE Mode):
  994.      *
  995.      *    Block or enable the menu entries associated with
  996.      *    functions to access the screen raster.
  997.      */
  998.  
  999. VOID __regargs
  1000. SetRasterMenu(BYTE Mode)
  1001. {
  1002.     if(Window && Menu)
  1003.     {
  1004.         if(Mode)
  1005.         {
  1006.             OnItem(MEN_SAVE_AS_TEXT);
  1007.             OnItem(MEN_PRINT_SCREEN);
  1008.         }
  1009.         else
  1010.         {
  1011.             OffItem(MEN_SAVE_AS_TEXT);
  1012.             OffItem(MEN_PRINT_SCREEN);
  1013.         }
  1014.     }
  1015. }
  1016.  
  1017.     /* PickFont(struct Window *Window,STRPTR Name,WORD *Points,BYTE MonoSpaced):
  1018.      *
  1019.      *    Pick a font using asl.library
  1020.      */
  1021.  
  1022. BYTE __regargs
  1023. PickFont(struct Window *Window,STRPTR Name,WORD *Points,BYTE MonoSpaced)
  1024. {
  1025.     struct FontRequester    *Requester;
  1026.     BYTE             Result = FALSE;
  1027.     LONG             Left    = 0,
  1028.                  Top    = 0,
  1029.                  Width    = 0,
  1030.                  Height    = 0;
  1031.  
  1032.     GetWindowInfo(WINDOW_FONT,&Left,&Top,&Width,&Height,Window -> Width / 2,Window -> Height / 2);
  1033.  
  1034.     if(Requester = (struct FontRequester *)AllocAslRequestTags(ASL_FontRequest,
  1035.         ASL_Window,                    Window,
  1036.         ASL_LeftEdge,                    Left,
  1037.         ASL_TopEdge,                    Top,
  1038.         ASL_Width,                    Width,
  1039.         ASL_Height,                    Height,
  1040.         MonoSpaced ? ASL_FuncFlags : TAG_IGNORE,    FONF_FIXEDWIDTH,
  1041.     TAG_DONE))
  1042.     {
  1043.         if(AslRequestTags(Requester,
  1044.             ASL_FontName,    Name,
  1045.             ASL_FontHeight,    *Points,
  1046.         TAG_DONE))
  1047.         {
  1048.             PutWindowInfo(WINDOW_FONT,Requester -> fo_LeftEdge,Requester -> fo_TopEdge,Requester -> fo_Width,Requester -> fo_Height);
  1049.  
  1050.             strcpy(Name,Requester -> fo_Attr . ta_Name);
  1051.  
  1052.             *Points = Requester -> fo_Attr . ta_YSize;
  1053.  
  1054.             Result = TRUE;
  1055.         }
  1056.  
  1057.         FreeAslRequest(Requester);
  1058.     }
  1059.  
  1060.     return(Result);
  1061. }
  1062.  
  1063.     /* ExtractString():
  1064.      *
  1065.      *    Extracts a string from a list separated by `|' characters.
  1066.      */
  1067.  
  1068. STRPTR __regargs
  1069. ExtractString(STRPTR String,STRPTR Destination,BYTE ReturnEnd)
  1070. {
  1071.     STRPTR OldString;
  1072.  
  1073.     if(ReturnEnd)
  1074.         OldString = NULL;
  1075.     else
  1076.         OldString = String;
  1077.  
  1078.     while(*String)
  1079.     {
  1080.         if(*String == '|')
  1081.         {
  1082.             *Destination = 0;
  1083.  
  1084.             String++;
  1085.  
  1086.             if(*String)
  1087.                 return(String);
  1088.             else
  1089.                 return(OldString);
  1090.         }
  1091.         else
  1092.             *Destination++ = *String++;
  1093.     }
  1094.  
  1095.     *Destination = 0;
  1096.  
  1097.     return(OldString);
  1098. }
  1099.  
  1100.     /* GetListSize(struct List *List):
  1101.      *
  1102.      *    Determine the number of entries in a list.
  1103.      */
  1104.  
  1105. LONG __regargs
  1106. GetListSize(struct List *List)
  1107. {
  1108.     struct Node    *Node    = List -> lh_Head;
  1109.     LONG         i    = 0;
  1110.  
  1111.     while(Node -> ln_Succ)
  1112.     {
  1113.         i++;
  1114.  
  1115.         Node = Node -> ln_Succ;
  1116.     }
  1117.  
  1118.     return(i);
  1119. }
  1120.  
  1121.     /* GetListNode(LONG Offset,struct List *List):
  1122.      *
  1123.      *    Return the n-th Node entry in a standard exec list.
  1124.      */
  1125.  
  1126. struct Node * __regargs
  1127. GetListNode(LONG Offset,struct List *List)
  1128. {
  1129.     struct Node    *Node;
  1130.     LONG         i;
  1131.  
  1132.     Node = List -> lh_Head;
  1133.  
  1134.     for(i = 0 ; i < Offset ; i++)
  1135.     {
  1136.         if(!Node -> ln_Succ -> ln_Succ)
  1137.             return(NULL);
  1138.  
  1139.         Node = Node -> ln_Succ;
  1140.     }
  1141.  
  1142.     return(Node);
  1143. }
  1144.  
  1145.     /* CreateNode(STRPTR Name): 
  1146.      *
  1147.      *    Put a name string into a list node.
  1148.      */
  1149.  
  1150. struct Node * __regargs
  1151. CreateNode(STRPTR Name)
  1152. {
  1153.     struct Node *Node;
  1154.  
  1155.     if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + strlen(Name) + 1,MEMF_ANY | MEMF_PUBLIC))
  1156.     {
  1157.         Node -> ln_Name = (STRPTR)(Node + 1);
  1158.  
  1159.         strcpy(Node -> ln_Name,Name);
  1160.     }
  1161.  
  1162.     return(Node);
  1163. }
  1164.  
  1165.     /* FreeNode(struct Node *Node):
  1166.      *
  1167.      *    Remove and deallocate a node.
  1168.      */
  1169.  
  1170. VOID __regargs
  1171. FreeNode(struct Node *Node)
  1172. {
  1173.     Remove(Node);
  1174.  
  1175.     FreeVecPooled(Node);
  1176. }
  1177.  
  1178.     /* FreeList(struct List *List):
  1179.      *
  1180.      *    Remove all nodes from the list
  1181.      *    and free them on the way.
  1182.      */
  1183.  
  1184. VOID __regargs
  1185. FreeList(struct List *List)
  1186. {
  1187.     struct Node *Node,*NextNode;
  1188.  
  1189.     Node = List -> lh_Head;
  1190.  
  1191.     while(NextNode = Node -> ln_Succ)
  1192.     {
  1193.         Remove(Node);
  1194.  
  1195.         FreeNode(Node);
  1196.  
  1197.         Node = NextNode;
  1198.     }
  1199. }
  1200.  
  1201.     /* GetNodeOffset(struct Node *Node,struct List *List):
  1202.      *
  1203.      *    Scan a list for a certain node and return
  1204.      *    its position.
  1205.      */
  1206.  
  1207. LONG __regargs
  1208. GetNodeOffset(struct Node *Node,struct List *List)
  1209. {
  1210.     struct Node    *ListNode;
  1211.     LONG         Offset = 0;
  1212.  
  1213.     ListNode = List -> lh_Head;
  1214.  
  1215.     while(ListNode -> ln_Succ)
  1216.     {
  1217.         if(Node == ListNode)
  1218.             return(Offset);
  1219.         else
  1220.         {
  1221.             Offset++;
  1222.  
  1223.             ListNode = ListNode -> ln_Succ;
  1224.         }
  1225.     }
  1226.  
  1227.     return(~0);
  1228. }
  1229.  
  1230.     /* MoveList(struct List *From,struct List *To):
  1231.      *
  1232.      *    Move the contents of a list to a different list.
  1233.      */
  1234.  
  1235. VOID __regargs
  1236. MoveList(struct List *From,struct List *To)
  1237. {
  1238.     struct Node *Node,*NextNode;
  1239.  
  1240.     Node = From -> lh_Head;
  1241.  
  1242.     while(NextNode = Node -> ln_Succ)
  1243.     {
  1244.         Remove(Node);
  1245.  
  1246.         AddTail(To,Node);
  1247.  
  1248.         Node = NextNode;
  1249.     }
  1250. }
  1251.  
  1252.     /* LogAction(STRPTR String,...):
  1253.      *
  1254.      *    Write an action to the default log file.
  1255.      */
  1256.  
  1257. VOID __stdargs
  1258. LogAction(STRPTR String,...)
  1259. {
  1260.     if(Config -> CaptureConfig -> LogActions && Config -> CaptureConfig -> LogFileName[0])
  1261.     {
  1262.         UBYTE    DummyBuffer[512];
  1263.         BPTR    File;
  1264.  
  1265.         va_list    VarArgs;
  1266.  
  1267.             /* Build a valid string. */
  1268.  
  1269.         va_start(VarArgs,String);
  1270.         VSPrintf(DummyBuffer,String,VarArgs);
  1271.         va_end(VarArgs);
  1272.  
  1273.             /* Does the log file already exist? */
  1274.  
  1275.         if(GetFileSize(Config -> CaptureConfig -> LogFileName))
  1276.         {
  1277.                 /* It does, let's append the data. */
  1278.  
  1279.             if(File = Open(Config -> CaptureConfig -> LogFileName,MODE_READWRITE))
  1280.             {
  1281.                 if(Seek(File,0,OFFSET_END) == -1)
  1282.                 {
  1283.                     Close(File);
  1284.  
  1285.                     File = NULL;
  1286.                 }
  1287.             }
  1288.         }
  1289.         else
  1290.         {
  1291.                 /* Create a new file. */
  1292.  
  1293.             if(File = Open(Config -> CaptureConfig -> LogFileName,MODE_NEWFILE))
  1294.                 FPrintf(File,LocaleString(MSG_TERMAUX_DATE_TIME_ACTION_TXT));
  1295.         }
  1296.  
  1297.             /* The file is open, build the date/time string and
  1298.              * write the log action.
  1299.              */
  1300.  
  1301.         if(File)
  1302.         {
  1303.             UBYTE        DateBuffer[40],
  1304.                     TimeBuffer[40];
  1305.             struct DateTime    DateTime;
  1306.  
  1307.             DateStamp(&DateTime . dat_Stamp);
  1308.  
  1309.             DateTime . dat_Format    = FORMAT_DOS;
  1310.             DateTime . dat_Flags    = NULL;
  1311.             DateTime . dat_StrDay    = NULL;
  1312.             DateTime . dat_StrDate    = DateBuffer;
  1313.             DateTime . dat_StrTime    = TimeBuffer;
  1314.  
  1315.             if(DateToStr(&DateTime))
  1316.             {
  1317.                 StripSpaces(TimeBuffer);
  1318.  
  1319.                 FPrintf(File,"%-9s %8s %s\n",DateBuffer,TimeBuffer,DummyBuffer);
  1320.             }
  1321.  
  1322.                 /* Done! */
  1323.  
  1324.             Close(File);
  1325.         }
  1326.     }
  1327. }
  1328.  
  1329.     /* FlushMsg(struct Window *Window):
  1330.      *
  1331.      *    Cancel all pending messages of a window.
  1332.      */
  1333.  
  1334. VOID __regargs
  1335. FlushMsg(struct Window *Window)
  1336. {
  1337.     struct IntuiMessage *Massage;
  1338.  
  1339.     while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  1340.         ReplyMsg(&Massage -> ExecMessage);
  1341. }
  1342.  
  1343.     /* GetString(STRPTR Prompt,STRPTR Buffer):
  1344.      *
  1345.      *    Get a string from the user, very much the same as xpr_gets,
  1346.      *    but also including the `Load File' gadget.
  1347.      */
  1348.  
  1349. BYTE __regargs
  1350. GetString(BYTE LoadGadget,BYTE Password,WORD MaxChars,STRPTR Prompt,STRPTR Buffer)
  1351. {
  1352.     enum    {    GAD_OK=1,GAD_CANCEL,GAD_STRING };
  1353.  
  1354.     struct LayoutHandle    *Handle;
  1355.     BYTE             Success = FALSE;
  1356.     UBYTE             LocalBuffer[256];
  1357.  
  1358.     if(MaxChars > 255)
  1359.     {
  1360.         CopyMem(Buffer,LocalBuffer,255);
  1361.  
  1362.         LocalBuffer[255] = 0;
  1363.  
  1364.         MaxChars = 255;
  1365.     }
  1366.     else
  1367.         strcpy(LocalBuffer,Buffer);
  1368.  
  1369.     if(!Prompt)
  1370.         Prompt = LocaleString(MSG_TERMXPR_INPUT_REQUIRED_TXT);
  1371.  
  1372.     if(Handle = LT_CreateHandleTags(Window -> WScreen,
  1373.         LH_LocaleHook,    &LocaleHook,
  1374.     TAG_DONE))
  1375.     {
  1376.         struct Window *PanelWindow;
  1377.  
  1378.         LT_New(Handle,
  1379.             LA_Type,    VERTICAL_KIND,
  1380.         TAG_DONE);
  1381.         {
  1382.             LT_New(Handle,
  1383.                 LA_Type,    VERTICAL_KIND,
  1384.                 LA_LabelText,    Prompt,
  1385.             TAG_DONE);
  1386.             {
  1387.                 if(Password)
  1388.                 {
  1389.                     LT_New(Handle,
  1390.                         LA_Type,    PASSWORD_KIND,
  1391.                         LA_STRPTR,    LocalBuffer,
  1392.                         LA_ID,        GAD_STRING,
  1393.                         LA_Chars,    40,
  1394.                         GTST_MaxChars,    MaxChars,
  1395.                     TAG_DONE);
  1396.                 }
  1397.                 else
  1398.                 {
  1399.                     LT_New(Handle,
  1400.                         LA_Type,    STRING_KIND,
  1401.                         LA_STRPTR,    LocalBuffer,
  1402.                         LA_ID,        GAD_STRING,
  1403.                         LA_Chars,    60,
  1404.                         LAST_Picker,    LoadGadget,
  1405.                     TAG_DONE);
  1406.                 }
  1407.  
  1408.                 LT_EndGroup(Handle);
  1409.             }
  1410.  
  1411.             LT_New(Handle,
  1412.                 LA_Type,VERTICAL_KIND,
  1413.             TAG_DONE);
  1414.             {
  1415.                 LT_New(Handle,
  1416.                     LA_Type,    XBAR_KIND,
  1417.                     LAXB_FullSize,    TRUE,
  1418.                 TAG_DONE);
  1419.  
  1420.                 LT_EndGroup(Handle);
  1421.             }
  1422.  
  1423.             LT_New(Handle,LA_Type,HORIZONTAL_KIND,
  1424.                 LAGR_SameSize,    TRUE,
  1425.                 LAGR_Spread,    TRUE,
  1426.             TAG_DONE);
  1427.             {
  1428.                 LT_New(Handle,
  1429.                     LA_Type,    BUTTON_KIND,
  1430.                     LA_LabelID,    MSG_TERMXPR_OKAY_GAD,
  1431.                     LA_ID,        GAD_OK,
  1432.                     LABT_ReturnKey,    TRUE,
  1433.                     LABT_ExtraFat,    TRUE,
  1434.                 TAG_DONE);
  1435.  
  1436.                 LT_New(Handle,
  1437.                     LA_Type,    BUTTON_KIND,
  1438.                     LA_LabelID,    MSG_GLOBAL_CANCEL_GAD,
  1439.                     LA_ID,        GAD_CANCEL,
  1440.                     LABT_EscKey,    TRUE,
  1441.                     LABT_ExtraFat,    TRUE,
  1442.                 TAG_DONE);
  1443.  
  1444.                 LT_EndGroup(Handle);
  1445.             }
  1446.         }
  1447.  
  1448.         if(PanelWindow = LT_Layout(Handle,LocaleString(MSG_GLOBAL_ENTER_TEXT_TXT),NULL,0,0,IDCMP_CLOSEWINDOW,0,
  1449.             LAWN_HelpHook,        &GuideHook,
  1450.             LAWN_Parent,        Window,
  1451.             WA_DepthGadget,        TRUE,
  1452.             WA_CloseGadget,        TRUE,
  1453.             WA_DragBar,        TRUE,
  1454.             WA_RMBTrap,        TRUE,
  1455.             WA_Activate,        TRUE,
  1456.         TAG_DONE))
  1457.         {
  1458.             struct IntuiMessage    *Message;
  1459.             BOOLEAN             Done = FALSE;
  1460.             ULONG             MsgClass,
  1461.                          MsgQualifier;
  1462.             UWORD             MsgCode;
  1463.             struct Gadget        *MsgGadget;
  1464.  
  1465.             LT_Activate(Handle,GAD_STRING);
  1466.  
  1467.             PushWindow(PanelWindow);
  1468.  
  1469.             LT_ShowWindow(Handle,TRUE);
  1470.  
  1471.             do
  1472.             {
  1473.                 if(Wait(PORTMASK(PanelWindow -> UserPort) | SIG_BREAK) & SIG_BREAK)
  1474.                     break;
  1475.  
  1476.                 while(Message = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort))
  1477.                 {
  1478.                     MsgClass    = Message -> Class;
  1479.                     MsgQualifier    = Message -> Qualifier;
  1480.                     MsgCode        = Message -> Code;
  1481.                     MsgGadget    = (struct Gadget *)Message -> IAddress;
  1482.  
  1483.                     GT_ReplyIMsg(Message);
  1484.  
  1485.                     LT_HandleInput(Handle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);
  1486.  
  1487.                     if(MsgClass == IDCMP_CLOSEWINDOW)
  1488.                         Done = TRUE;
  1489.  
  1490.                     if(MsgClass == IDCMP_GADGETUP)
  1491.                     {
  1492.                         switch(MsgGadget -> GadgetID)
  1493.                         {
  1494.                             case GAD_STRING:
  1495.  
  1496.                                 if(MsgCode == '\r')
  1497.                                 {
  1498.                                     strcpy(Buffer,LocalBuffer);
  1499.  
  1500.                                     Success = Done = TRUE;
  1501.  
  1502.                                     LT_PressButton(Handle,GAD_OK);
  1503.                                 }
  1504.  
  1505.                                 break;
  1506.  
  1507.                             case GAD_OK:
  1508.  
  1509.                                 strcpy(Buffer,LocalBuffer);
  1510.  
  1511.                                 Success = Done = TRUE;
  1512.                                 break;
  1513.  
  1514.                             case GAD_CANCEL:
  1515.  
  1516.                                 Done = TRUE;
  1517.                                 break;
  1518.                         }
  1519.                     }
  1520.  
  1521.                     if(MsgClass == IDCMP_IDCMPUPDATE && MsgGadget -> GadgetID == GAD_STRING)
  1522.                     {
  1523.                         UBYTE             DummyBuffer[MAX_FILENAME_LENGTH],
  1524.                                     *DummyChar;
  1525.                         struct FileRequester    *FileRequest;
  1526.  
  1527.                         LT_LockWindow(PanelWindow);
  1528.  
  1529.                         SplitFileName(LocalBuffer,&DummyChar,DummyBuffer);
  1530.  
  1531.                         if(FileRequest = GetFile(PanelWindow,LocaleString(MSG_TERMAUX_LOAD_FILE_TXT),DummyBuffer,DummyChar,DummyBuffer,NULL,FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SELECT_TXT),TRUE))
  1532.                         {
  1533.                             LT_SetAttributes(Handle,GAD_STRING,GTST_String,DummyBuffer,TAG_DONE);
  1534.  
  1535.                             FreeAslRequest(FileRequest);
  1536.                         }
  1537.  
  1538.                         LT_UnlockWindow(PanelWindow);
  1539.                     }
  1540.                 }
  1541.             }
  1542.             while(!Done);
  1543.  
  1544.             PopWindow();
  1545.         }
  1546.  
  1547.         LT_DeleteHandle(Handle);
  1548.     }
  1549.  
  1550.     return(Success);
  1551. }
  1552.  
  1553.     /* WakeUp(struct Window *Window,WORD Sound):
  1554.      *
  1555.      *    Pop a window to the front and alert the user.
  1556.      */
  1557.  
  1558. VOID __regargs
  1559. WakeUp(struct Window *Window,WORD Sound)
  1560. {
  1561.     if(Window)
  1562.     {
  1563.         if(Config -> TerminalConfig -> AlertMode == ALERT_SCREEN || Config -> TerminalConfig -> AlertMode == ALERT_BEEP_SCREEN)
  1564.         {
  1565.             if(Window -> WScreen -> LeftEdge > 0)
  1566.             {
  1567.                 if(Window -> WScreen -> TopEdge > 0)
  1568.                     MoveScreen(Window -> WScreen,-Window -> WScreen -> LeftEdge,-Window -> WScreen -> TopEdge);
  1569.                 else
  1570.                     MoveScreen(Window -> WScreen,-Window -> WScreen -> LeftEdge,0);
  1571.             }
  1572.             else
  1573.             {
  1574.                 if(Window -> WScreen -> TopEdge > 0)
  1575.                     MoveScreen(Window -> WScreen,0,-Window -> WScreen -> TopEdge);
  1576.             }
  1577.  
  1578.             WindowToFront(Window);
  1579.  
  1580.             ScreenToFront(Window -> WScreen);
  1581.         }
  1582.     }
  1583.  
  1584.     if(Sound != SOUND_BELL || Config -> TerminalConfig -> AlertMode == ALERT_BEEP || Config -> TerminalConfig -> AlertMode == ALERT_BEEP_SCREEN)
  1585.         SoundPlay(Sound);
  1586. }
  1587.  
  1588.     /* TaskDestructor(struct DataMsg *Item):
  1589.      *
  1590.      *    Msg destructor for the routines below.
  1591.      */
  1592.  
  1593. STATIC VOID __stdargs
  1594. TaskDestructor(struct DataMsg *Item)
  1595. {
  1596.     Signal((struct Process *)Item -> Data,SIGBREAKF_CTRL_F);
  1597. }
  1598.  
  1599.     /* AmigaDOSBackgroundServer(VOID):
  1600.      *
  1601.      *    Background process to handle tool execution.
  1602.      */
  1603.  
  1604. STATIC VOID __saveds
  1605. AmigaDOSBackgroundServer(VOID)
  1606. {
  1607.     BPTR         OldCOS,
  1608.              NewCOS = NULL;
  1609.     struct DataMsg     Msg;
  1610.     STRPTR         Command;
  1611.     struct Process    *Me;
  1612.  
  1613.         /* Look who we are. */
  1614.  
  1615.     Me = (struct Process *)SysBase -> ThisTask;
  1616.  
  1617.     Command = Me -> pr_Task . tc_UserData;
  1618.  
  1619.         /* Create console output stream, will be closed automagically on exit. */
  1620.  
  1621.     if(!Me -> pr_COS && Me -> pr_ConsoleTask)
  1622.     {
  1623.         if(NewCOS = Open("*",MODE_NEWFILE))
  1624.         {
  1625.             OldCOS = Me -> pr_COS;
  1626.  
  1627.             Me -> pr_COS = NewCOS;
  1628.         }
  1629.     }
  1630.  
  1631.     SystemTags(Command,
  1632.         SYS_UserShell,    TRUE,
  1633.     TAG_DONE);
  1634.  
  1635.     FreeVecPooled(Command);
  1636.  
  1637.     Forbid();
  1638.  
  1639.     InitMsgItem(&Msg,TaskDestructor);
  1640.  
  1641.     Msg . Type = DATAMSGTYPE_COMMANDDONE;
  1642.     Msg . Data = (UBYTE *)Me;
  1643.  
  1644.     ClrSignal(SIGBREAKF_CTRL_F);
  1645.  
  1646.     PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  1647.  
  1648.     Wait(SIGBREAKF_CTRL_F);
  1649.  
  1650.     if(NewCOS)
  1651.     {
  1652.         Me -> pr_COS = OldCOS;
  1653.  
  1654.         Close(NewCOS);
  1655.     }
  1656. }
  1657.  
  1658.     /* SendAmigaDOSCommand(STRPTR Name):
  1659.      *
  1660.      *    Let the current default Shell execute an AmigaDOS
  1661.      *    command. Block until the command has returned.
  1662.      */
  1663.  
  1664. VOID __regargs
  1665. SendAmigaDOSCommand(STRPTR Name)
  1666. {
  1667.     STRPTR NewName;
  1668.  
  1669.     if(NewName = (STRPTR)AllocVecPooled(strlen(Name) + 1 + 256,MEMF_ANY))
  1670.     {
  1671.         struct Process    *NewProcess;
  1672.         BPTR         Stream;
  1673.         STRPTR         NewWindowName;
  1674.  
  1675.         strcpy(NewName,Name);
  1676.  
  1677.         NewWindowName = NewName + strlen(NewName) + 1;
  1678.  
  1679.         BlockWindows();
  1680.  
  1681.         SetQueueDiscard(SpecialQueue,FALSE);
  1682.  
  1683.             /* Open the output file. */
  1684.  
  1685.         if(WindowName[0])
  1686.         {
  1687.             UBYTE LocalName[MAXPUBSCREENNAME + 1];
  1688.  
  1689.             if(Window)
  1690.             {
  1691.                 if(!GetPubScreenName(Window -> WScreen,LocalName))
  1692.                     LocalName[0] = 0;
  1693.             }
  1694.  
  1695.             if(LocalName[0])
  1696.             {
  1697.                 SPrintf(NewWindowName,WindowName,LocalName);
  1698.  
  1699.                 Stream = Open(NewWindowName,MODE_NEWFILE);
  1700.             }
  1701.             else
  1702.                 Stream = Open(WindowName,MODE_NEWFILE);
  1703.         }
  1704.         else
  1705.             Stream = NULL;
  1706.  
  1707.         Forbid();
  1708.  
  1709.         if(Stream)
  1710.         {
  1711.             if(GoodStream(Stream))
  1712.             {
  1713.                 struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
  1714.  
  1715.                 NewProcess = (struct Process *)CreateNewProcTags(
  1716.                     NP_Entry,    AmigaDOSBackgroundServer,
  1717.                     NP_Name,    "term AmigaDOS Background Process",
  1718.                     NP_Input,    Stream,
  1719.                     NP_Output,    NULL,
  1720.                     NP_Cli,        TRUE,
  1721.                     NP_ConsoleTask,    Handle -> fh_Type,
  1722.                     NP_StackSize,    16384,
  1723.                 TAG_END);
  1724.             }
  1725.             else
  1726.             {
  1727.                 NewProcess = (struct Process *)CreateNewProcTags(
  1728.                     NP_Entry,    AmigaDOSBackgroundServer,
  1729.                     NP_Name,    "term AmigaDOS Background Process",
  1730.                     NP_Output,    Stream,
  1731.                     NP_Cli,        TRUE,
  1732.                     NP_ConsoleTask,    NULL,
  1733.                     NP_StackSize,    16384,
  1734.                 TAG_END);
  1735.             }
  1736.         }
  1737.         else
  1738.         {
  1739.             NewProcess = (struct Process *)CreateNewProcTags(
  1740.                 NP_Entry,    AmigaDOSBackgroundServer,
  1741.                 NP_Name,    "term AmigaDOS Background Process",
  1742.                 NP_Cli,        TRUE,
  1743.                 NP_ConsoleTask,    NULL,
  1744.                 NP_StackSize,    16384,
  1745.             TAG_END);
  1746.         }
  1747.  
  1748.             /* Did we succeed in creating the process? */
  1749.  
  1750.         if(NewProcess)
  1751.         {
  1752.             CantQuit++;
  1753.  
  1754.             NewProcess -> pr_Task . tc_UserData = NewName;
  1755.  
  1756.             Permit();
  1757.         }
  1758.         else
  1759.         {
  1760.             Permit();
  1761.  
  1762.             if(Stream)
  1763.                 Close(Stream);
  1764.  
  1765.             FreeVecPooled(NewName);
  1766.  
  1767.             BumpWindow(Window);
  1768.  
  1769.             ReleaseWindows();
  1770.         }
  1771.     }
  1772. }
  1773.  
  1774.     /* RexxBackgroundServer():
  1775.      *
  1776.      *    The background process to handle the rexx
  1777.      *    massaging.
  1778.      */
  1779.  
  1780. STATIC VOID __saveds
  1781. RexxBackgroundServer(VOID)
  1782. {
  1783.     struct MsgPort     *RexxPort;
  1784.     BPTR         OldCOS,
  1785.              NewCOS = NULL;
  1786.     struct DataMsg     Msg;
  1787.     STRPTR         Command;
  1788.     struct Process    *Me;
  1789.  
  1790.         /* Look who we are. */
  1791.  
  1792.     Me = (struct Process *)SysBase -> ThisTask;
  1793.  
  1794.     Command = Me -> pr_Task . tc_UserData;
  1795.  
  1796.         /* Create console output stream, will be closed automagically on exit. */
  1797.  
  1798.     if(!Me -> pr_COS && Me -> pr_ConsoleTask)
  1799.     {
  1800.         if(NewCOS = Open("*",MODE_NEWFILE))
  1801.         {
  1802.             OldCOS = Me -> pr_COS;
  1803.  
  1804.             Me -> pr_COS = NewCOS;
  1805.         }
  1806.     }
  1807.  
  1808.     if(RexxPort = FindPort(RXSDIR))
  1809.     {
  1810.         struct MsgPort __aligned     ReplyPort;
  1811.         struct RexxMsg            *RexxMsg;
  1812.  
  1813.         InitSinglePort(&ReplyPort);
  1814.  
  1815.         if(RexxMsg = CreateRexxMsg(&ReplyPort,"term",RexxPortName))
  1816.         {
  1817.             if(RexxMsg -> rm_Args[0] = CreateArgstring(Command,strlen(Command)))
  1818.             {
  1819.                 RexxMsg -> rm_Action = RXCOMM;
  1820.  
  1821.                 Forbid();
  1822.  
  1823.                 ClrSignal(SIGF_SINGLE);
  1824.  
  1825.                 PutMsg(RexxPort,(struct Message *)RexxMsg);
  1826.  
  1827.                 WaitPort(&ReplyPort);
  1828.  
  1829.                 GetMsg(&ReplyPort);
  1830.  
  1831.                 Permit();
  1832.  
  1833.                     /* This doesn't look too
  1834.                      * good, does it?
  1835.                      */
  1836.  
  1837.                 if(RexxMsg -> rm_Result1 && Me -> pr_COS)
  1838.                     Printf(LocaleString(MSG_TERMAUX_COMMAND_HAS_TERMINATED_TXT),Command,RexxMsg -> rm_Result1,RexxMsg -> rm_Result2);
  1839.  
  1840.                 DeleteArgstring(RexxMsg -> rm_Args[0]);
  1841.             }
  1842.  
  1843.             DeleteRexxMsg(RexxMsg);
  1844.         }
  1845.     }
  1846.  
  1847.     FreeVecPooled(Command);
  1848.  
  1849.     Forbid();
  1850.  
  1851.     InitMsgItem(&Msg,TaskDestructor);
  1852.  
  1853.     Msg . Type = DATAMSGTYPE_COMMANDDONE;
  1854.     Msg . Data = (UBYTE *)Me;
  1855.  
  1856.     ClrSignal(SIGBREAKF_CTRL_F);
  1857.  
  1858.     PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  1859.  
  1860.     Wait(SIGBREAKF_CTRL_F);
  1861.  
  1862.     if(NewCOS)
  1863.     {
  1864.         Me -> pr_COS = OldCOS;
  1865.  
  1866.         Close(NewCOS);
  1867.     }
  1868. }
  1869.  
  1870.     /* SendARexxCommand(STRPTR Name):
  1871.      *
  1872.      *    Let the ARexx server execute a command (or a script
  1873.      *    file if necessary) and block until the command
  1874.      *    has returned.
  1875.      */
  1876.  
  1877. VOID __regargs
  1878. SendARexxCommand(STRPTR Name)
  1879. {
  1880.     STRPTR NewName;
  1881.  
  1882.     if(NewName = (STRPTR)AllocVecPooled(strlen(Name) + 1 + 256,MEMF_ANY))
  1883.     {
  1884.         struct Process    *NewProcess;
  1885.         BPTR         Stream;
  1886.         STRPTR         NewWindowName;
  1887.  
  1888.         strcpy(NewName,Name);
  1889.  
  1890.         NewWindowName = NewName + strlen(NewName) + 1;
  1891.  
  1892.         BlockWindows();
  1893.  
  1894.         SetQueueDiscard(SpecialQueue,FALSE);
  1895.  
  1896.             /* Open the output file. */
  1897.  
  1898.         if(WindowName[0])
  1899.         {
  1900.             UBYTE LocalName[MAXPUBSCREENNAME + 1];
  1901.  
  1902.             if(Window)
  1903.             {
  1904.                 if(!GetPubScreenName(Window -> WScreen,LocalName))
  1905.                     LocalName[0] = 0;
  1906.             }
  1907.  
  1908.             if(LocalName[0])
  1909.             {
  1910.                 SPrintf(NewWindowName,WindowName,LocalName);
  1911.  
  1912.                 Stream = Open(NewWindowName,MODE_NEWFILE);
  1913.             }
  1914.             else
  1915.                 Stream = Open(WindowName,MODE_NEWFILE);
  1916.         }
  1917.         else
  1918.             Stream = NULL;
  1919.  
  1920.         Forbid();
  1921.  
  1922.             /* Create the background process which will
  1923.              * handle all the messy rexx message sending
  1924.              * for us.
  1925.              */
  1926.  
  1927.         if(Stream)
  1928.         {
  1929.             if(GoodStream(Stream))
  1930.             {
  1931.                 struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
  1932.  
  1933.                 NewProcess = (struct Process *)CreateNewProcTags(
  1934.                     NP_Entry,    RexxBackgroundServer,
  1935.                     NP_Name,    "term ARexx Background Process",
  1936.                     NP_Input,    Stream,
  1937.                     NP_Output,    NULL,
  1938.                     NP_Cli,        TRUE,
  1939.                     NP_ConsoleTask,    Handle -> fh_Type,
  1940.                     NP_StackSize,    16384,
  1941.                 TAG_END);
  1942.             }
  1943.             else
  1944.             {
  1945.                 NewProcess = (struct Process *)CreateNewProcTags(
  1946.                     NP_Entry,    RexxBackgroundServer,
  1947.                     NP_Name,    "term ARexx Background Process",
  1948.                     NP_Output,    Stream,
  1949.                     NP_Cli,        TRUE,
  1950.                     NP_ConsoleTask,    NULL,
  1951.                     NP_StackSize,    16384,
  1952.                 TAG_END);
  1953.             }
  1954.         }
  1955.         else
  1956.         {
  1957.             NewProcess = (struct Process *)CreateNewProcTags(
  1958.                 NP_Entry,    RexxBackgroundServer,
  1959.                 NP_Name,    "term ARexx Background Process",
  1960.                 NP_Cli,        TRUE,
  1961.                 NP_ConsoleTask,    NULL,
  1962.                 NP_StackSize,    16384,
  1963.             TAG_END);
  1964.         }
  1965.  
  1966.             /* Did we succeed in creating the process? */
  1967.  
  1968.         if(NewProcess)
  1969.         {
  1970.             CantQuit++;
  1971.  
  1972.             NewProcess -> pr_Task . tc_UserData = NewName;
  1973.  
  1974.             Permit();
  1975.         }
  1976.         else
  1977.         {
  1978.             Permit();
  1979.  
  1980.             if(Stream)
  1981.                 Close(Stream);
  1982.  
  1983.             FreeVecPooled(NewName);
  1984.  
  1985.             BumpWindow(Window);
  1986.  
  1987.             ReleaseWindows();
  1988.         }
  1989.     }
  1990. }
  1991.  
  1992.     /* BlockWindows():
  1993.      *
  1994.      *    Block the main window and the status window (i.e. disable
  1995.      *    the menu and attach a wait pointer).
  1996.      */
  1997.  
  1998. VOID
  1999. BlockWindows()
  2000. {
  2001.     if(!(BlockNestCount++))
  2002.     {
  2003.         LT_LockWindow(Window);
  2004.         LT_LockWindow(StatusWindow);
  2005.         LT_LockWindow(FastWindow);
  2006.  
  2007.         WeAreBlocking = TRUE;
  2008.  
  2009.         SetQueueDiscard(SpecialQueue,TRUE);
  2010.  
  2011.         GhostCursor();
  2012.     }
  2013. }
  2014.  
  2015.     /* ReleaseWindows():
  2016.      *
  2017.      *    Reenable the menus and clear the wait pointer.
  2018.      */
  2019.  
  2020. VOID
  2021. ReleaseWindows()
  2022. {
  2023.     if(BlockNestCount == 1)
  2024.     {
  2025.         LT_UnlockWindow(Window);
  2026.         LT_UnlockWindow(StatusWindow);
  2027.         LT_UnlockWindow(FastWindow);
  2028.  
  2029.         WeAreBlocking = FALSE;
  2030.  
  2031.         SetQueueDiscard(SpecialQueue,FALSE);
  2032.  
  2033.         if(Window)
  2034.         {
  2035.             Forbid();
  2036.  
  2037.             if(Window -> Flags & WFLG_WINDOWACTIVE)
  2038.                 NormalCursor();
  2039.  
  2040.             Permit();
  2041.         }
  2042.     }
  2043.  
  2044.     if(BlockNestCount)
  2045.         BlockNestCount--;
  2046. }
  2047.  
  2048.     /* LineRead(BPTR File,STRPTR Buffer,LONG MaxChars):
  2049.      *
  2050.      *    Read a few bytes from a file (à la gets).
  2051.      */
  2052.  
  2053. LONG __regargs
  2054. LineRead(BPTR File,STRPTR Buffer,LONG MaxChars)
  2055. {
  2056.     STATIC UBYTE __far    Data[1024];
  2057.     STATIC LONG        ReadIndex    = 0,
  2058.                 ReadLen        = 0;
  2059.  
  2060.     if(File)
  2061.     {
  2062.         LONG BytesRead = 0,i;
  2063.  
  2064.         for(i = 0 ; i < MaxChars ; i++)
  2065.         {
  2066.             if(ReadIndex >= ReadLen)
  2067.             {
  2068.                 ReadLen = Read(File,Data,1024);
  2069.  
  2070.                 ReadIndex = 0;
  2071.  
  2072.                 if(ReadLen <= 0)
  2073.                 {
  2074.                     Buffer[i] = 0;
  2075.  
  2076.                     return(BytesRead);
  2077.                 }
  2078.             }
  2079.  
  2080.             BytesRead++;
  2081.  
  2082.             if((Buffer[i] = Data[ReadIndex++]) == '\n')
  2083.             {
  2084.                 Buffer[i + 1] = 0;
  2085.  
  2086.                 return(BytesRead);
  2087.             }
  2088.         }
  2089.  
  2090.         return(BytesRead);
  2091.     }
  2092.     else
  2093.         ReadIndex = ReadLen = 0;
  2094. }
  2095.  
  2096.     /* GetBaudRate(STRPTR Buffer):
  2097.      *
  2098.      *    Calculate the baud rate contained in a connect string.
  2099.      */
  2100.  
  2101. LONG __regargs
  2102. GetBaudRate(STRPTR Buffer)
  2103. {
  2104.     LONG Rate,i,j;
  2105.  
  2106.     for(i = j = 0 ; i < strlen(Buffer) ; i++)
  2107.     {
  2108.         if(Buffer[i] == ' ')
  2109.             continue;
  2110.         else
  2111.         {
  2112.             if(Buffer[i] >= '0' && Buffer[i] <= '9')
  2113.                 SharedBuffer[j++] = Buffer[i];
  2114.             else
  2115.                 break;
  2116.         }
  2117.     }
  2118.  
  2119.     SharedBuffer[j] = 0;
  2120.  
  2121.     if(StrToLong(SharedBuffer,&Rate) > 0)
  2122.     {
  2123.         if(Rate > 0)
  2124.             return(Rate);
  2125.     }
  2126.  
  2127.     return(0);
  2128. }
  2129.  
  2130.     /* LookForIt(struct MenuItem *Item,ULONG ID):
  2131.      *
  2132.      *    Auxilary routine for FindThisItem(), scans
  2133.      *    menu item and sub item lists.
  2134.      */
  2135.  
  2136. STATIC struct MenuItem * __inline
  2137. LookForIt(struct MenuItem *Item,ULONG ID)
  2138. {
  2139.     while(Item)
  2140.     {
  2141.         if((ULONG)GTMENUITEM_USERDATA(Item) == ID)
  2142.             return(Item);
  2143.         else
  2144.         {
  2145.             if(Item -> SubItem)
  2146.             {
  2147.                 register struct MenuItem *TheItem;
  2148.  
  2149.                 if(TheItem = LookForIt(Item -> SubItem,ID))
  2150.                     return(TheItem);
  2151.             }
  2152.  
  2153.             Item = Item -> NextItem;
  2154.         }
  2155.     }
  2156.  
  2157.     return(NULL);
  2158. }
  2159.  
  2160.     /* FindThisItem(struct Menu *FirstMenu,ULONG MenuID):
  2161.      *
  2162.      *    Scan a menu for a menuitem associated with a
  2163.      *    menu ID.
  2164.      */
  2165.  
  2166. struct MenuItem * __regargs
  2167. FindThisItem(struct Menu *FirstMenu,ULONG MenuID)
  2168. {
  2169.     struct MenuItem *Item;
  2170.  
  2171.     while(FirstMenu)
  2172.     {
  2173.         if(Item = LookForIt(FirstMenu -> FirstItem,MenuID))
  2174.             return(Item);
  2175.         else
  2176.             FirstMenu = FirstMenu -> NextMenu;
  2177.     }
  2178.  
  2179.     return(NULL);
  2180. }
  2181.  
  2182.     /* GetItem(ULONG MenuID):
  2183.      *
  2184.      *    Get the checkmark state of a menu item.
  2185.      */
  2186.  
  2187. BYTE __regargs
  2188. GetItem(ULONG MenuID)
  2189. {
  2190.     if(Menu)
  2191.     {
  2192.         struct MenuItem *Item;
  2193.  
  2194.         if(Item = FindThisItem(Menu,MenuID))
  2195.         {
  2196.             if(Item -> Flags & CHECKED)
  2197.                 return(TRUE);
  2198.         }
  2199.     }
  2200.  
  2201.     return(FALSE);
  2202. }
  2203.  
  2204.     /* SetItem(ULONG MenuID,BYTE Mode):
  2205.      *
  2206.      *    Clear or set the checkmark or state of a menu item.
  2207.      */
  2208.  
  2209. VOID __regargs
  2210. SetItem(ULONG MenuID,BYTE Mode)
  2211. {
  2212.         /* Is the global pull-down menu available? */
  2213.  
  2214.     if(Menu)
  2215.     {
  2216.         struct MenuItem *Item;
  2217.  
  2218.             /* Try to find the menu item and change
  2219.              * the state of the checkmark.
  2220.              */
  2221.  
  2222.         if(Item = FindThisItem(Menu,MenuID))
  2223.         {
  2224.                 /* Remove the menu from the windows. */
  2225.  
  2226.             if(Window)
  2227.                 ClearMenuStrip(Window);
  2228.  
  2229.             if(StatusWindow)
  2230.                 ClearMenuStrip(StatusWindow);
  2231.  
  2232.             if(FastWindow)
  2233.                 ClearMenuStrip(FastWindow);
  2234.  
  2235.             switch(Mode)
  2236.             {
  2237.                 case SETITEM_SETCHECK:
  2238.  
  2239.                     Item -> Flags |= CHECKED;
  2240.                     break;
  2241.  
  2242.                 case SETITEM_CLRCHECK:
  2243.  
  2244.                     Item -> Flags &= ~CHECKED;
  2245.                     break;
  2246.  
  2247.                 case SETITEM_ON:
  2248.  
  2249.                     Item -> Flags |= ITEMENABLED;
  2250.                     break;
  2251.  
  2252.                 case SETITEM_OFF:
  2253.  
  2254.                     Item -> Flags &= ~ITEMENABLED;
  2255.                     break;
  2256.             }
  2257.  
  2258.                 /* Reattach the menu to the windows. */
  2259.  
  2260.             if(Window)
  2261.                 ResetMenuStrip(Window,Menu);
  2262.  
  2263.             if(StatusWindow)
  2264.                 ResetMenuStrip(StatusWindow,Menu);
  2265.  
  2266.             if(FastWindow)
  2267.                 ResetMenuStrip(FastWindow,Menu);
  2268.         }
  2269.     }
  2270. }
  2271.  
  2272.     /* GetFileSize(STRPTR Name):
  2273.      *
  2274.      *    Simple routine to return the size of a file in
  2275.      *    bytes.
  2276.      */
  2277.  
  2278. LONG __regargs
  2279. GetFileSize(STRPTR Name)
  2280. {
  2281.     struct FileInfoBlock    *FileInfo;
  2282.     LONG             FileSize = 0;
  2283.  
  2284.     if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  2285.     {
  2286.         BPTR FileLock;
  2287.  
  2288.         if(FileLock = Lock(Name,ACCESS_READ))
  2289.         {
  2290.             if(Examine(FileLock,FileInfo))
  2291.             {
  2292.                 if(FileInfo -> fib_DirEntryType < 0)
  2293.                     FileSize = FileInfo -> fib_Size;
  2294.             }
  2295.  
  2296.             UnLock(FileLock);
  2297.         }
  2298.  
  2299.         FreeDosObject(DOS_FIB,FileInfo);
  2300.     }
  2301.  
  2302.     return(FileSize);
  2303. }
  2304.  
  2305.     /* GetFile(STRPTR Title,STRPTR Directory,STRPTR Name,STRPTR Buffer,STRPTR Pattern,BYTE SaveFlag,BYTE MultiSelect):
  2306.      *
  2307.      *    Call the asl.library file requester to select a single or
  2308.      *    a couple of files.
  2309.      */
  2310.  
  2311. struct FileRequester * __regargs
  2312. GetFile(struct Window *Parent,STRPTR Title,STRPTR Directory,STRPTR Name,STRPTR Buffer,STRPTR Pattern,BYTE SaveFlag,BYTE MultiSelect,BYTE DirsOnly,STRPTR OKText,BYTE AskWrite)
  2313. {
  2314.     STATIC UBYTE __far     DirBuffer[MAX_FILENAME_LENGTH],
  2315.                  PatternBuffer[60];
  2316.  
  2317.     struct FileRequester    *AslFileRequest;
  2318.     BYTE             Result        = FALSE,
  2319.                  DefaultPattern    = FALSE;
  2320.     LONG             Flags,ExtFlags = 0;
  2321.     WORD             i,j;
  2322.  
  2323.     UBYTE             OtherTitle[60];
  2324.     LONG             Left    = 0,
  2325.                  Top    = 0,
  2326.                  Width    = 0,
  2327.                  Height    = 0;
  2328.  
  2329.     if(!Parent)
  2330.         Parent = Window;
  2331.  
  2332.     for(i = j = 0 ; i < strlen(Title) ; i++)
  2333.     {
  2334.         if(Title[i] != '_')
  2335.             OtherTitle[j++] = Title[i];
  2336.     }
  2337.  
  2338.     OtherTitle[j] = 0;
  2339.  
  2340.     Title = OtherTitle;
  2341.  
  2342.     if(DirsOnly)
  2343.     {
  2344.         ExtFlags |= FIL1F_NOFILES;
  2345.  
  2346.         if(Pattern)
  2347.             ExtFlags |= FIL1F_MATCHDIRS;
  2348.     }
  2349.  
  2350.     GetWindowInfo(WINDOW_FILE,&Left,&Top,&Width,&Height,Window -> Width / 2,Window -> Height / 2);
  2351.  
  2352.         /* Empty directory string? Revert to the last directory
  2353.          * name.
  2354.          */
  2355.  
  2356.     Forbid();
  2357.  
  2358.     if(!Directory[0])
  2359.     {
  2360.         if(!DirBuffer[0])
  2361.         {
  2362.             UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
  2363.  
  2364.             if(!GetCurrentDirName(LocalBuffer,MAX_FILENAME_LENGTH))
  2365.                 LocalBuffer[0] = 0;
  2366.  
  2367.             if(!DirBuffer[0])
  2368.                 strcpy(DirBuffer,LocalBuffer);
  2369.         }
  2370.  
  2371.         Directory = DirBuffer;
  2372.     }
  2373.  
  2374.         /* If a wildcard pattern is required, add a gadget
  2375.          * to display it.
  2376.          */
  2377.  
  2378.     if(Pattern)
  2379.     {
  2380.         Flags = FILF_PATGAD;
  2381.  
  2382.         if(!Pattern[0])
  2383.         {
  2384.             DefaultPattern = TRUE;
  2385.  
  2386.             if(PatternBuffer[0])
  2387.                 Pattern = PatternBuffer;
  2388.             else
  2389.                 Pattern = "#?";
  2390.         }
  2391.         else
  2392.         {
  2393.             if(!Stricmp(Pattern,"#?") || !Stricmp(Pattern,PatternBuffer))
  2394.             {
  2395.                 DefaultPattern = TRUE;
  2396.  
  2397.                 Pattern = PatternBuffer;
  2398.             }
  2399.         }
  2400.     }
  2401.     else
  2402.     {
  2403.         Flags = 0;
  2404.  
  2405.         Pattern = "#?";
  2406.     }
  2407.  
  2408.     Permit();
  2409.  
  2410.         /* Set the save flag if we are about to save something. */
  2411.  
  2412.     if(SaveFlag)
  2413.         Flags |= FILF_SAVE;
  2414.  
  2415.         /* Set the multiselect bit if multiple files are
  2416.          * to be selected (e.g. for batch file upload).
  2417.          */
  2418.  
  2419.     if(MultiSelect)
  2420.         Flags |= FILF_MULTISELECT;
  2421.  
  2422.         /* Provide a standard `Ok' text if none
  2423.          * specified.
  2424.          */
  2425.  
  2426.     if(!OKText)
  2427.         OKText = (SaveFlag ? LocaleString(MSG_GLOBAL_SAVE_TXT) : LocaleString(MSG_GLOBAL_OPEN_TXT));
  2428.  
  2429.         /* Allocate the asl.library directory requester
  2430.          * and display it.
  2431.          */
  2432.  
  2433.     if(AslFileRequest = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
  2434.         ASL_Window,    Parent,
  2435.         ASL_File,    Name,
  2436.         ASL_Dir,    Directory,
  2437.         Title ? ASL_Hail : TAG_IGNORE,    Title,
  2438.         ASL_FuncFlags,    Flags | FILF_NEWIDCMP,
  2439.         ASL_Pattern,    Pattern,
  2440.         ASL_OKText,    OKText,
  2441.         ASL_ExtFlags1,    ExtFlags,
  2442.         ASLFR_TextAttr,    &UserFont,
  2443.         ASL_LeftEdge,    Left,
  2444.         ASL_TopEdge,    Top,
  2445.         ASL_Width,    Width,
  2446.         ASL_Height,    Height,
  2447.     TAG_DONE))
  2448.     {
  2449.         if(AslRequestTags(AslFileRequest,TAG_DONE))
  2450.         {
  2451.             PutWindowInfo(WINDOW_FILE,AslFileRequest -> rf_LeftEdge,AslFileRequest -> rf_TopEdge,AslFileRequest -> rf_Width,AslFileRequest -> rf_Height);
  2452.  
  2453.             if(!DirsOnly)
  2454.             {
  2455.                 STRPTR FileName;
  2456.  
  2457.                 if(AslFileRequest -> rf_NumArgs > 1 && AslFileRequest -> rf_ArgList)
  2458.                     FileName = AslFileRequest -> rf_ArgList -> wa_Name;
  2459.                 else
  2460.                     FileName = AslFileRequest -> rf_File;
  2461.  
  2462.                     /* Do we have a valid file name? */
  2463.  
  2464.                 if(FileName)
  2465.                 {
  2466.                         /* Build a legal path/file string. */
  2467.  
  2468.                     strcpy(Buffer,AslFileRequest -> rf_Dir);
  2469.  
  2470.                     AddPart((STRPTR)Buffer,FileName,MAX_FILENAME_LENGTH);
  2471.  
  2472.                     Result = TRUE;
  2473.  
  2474.                     Forbid();
  2475.  
  2476.                     strcpy(DirBuffer,AslFileRequest -> rf_Dir);
  2477.  
  2478.                     Permit();
  2479.                 }
  2480.             }
  2481.             else
  2482.             {
  2483.                 if(AslFileRequest -> rf_Dir[0])
  2484.                 {
  2485.                     strcpy(Buffer,AslFileRequest -> rf_Dir);
  2486.  
  2487.                     Result = TRUE;
  2488.  
  2489.                     Forbid();
  2490.  
  2491.                     strcpy(DirBuffer,AslFileRequest -> rf_Dir);
  2492.  
  2493.                     Permit();
  2494.                 }
  2495.             }
  2496.         }
  2497.     }
  2498.  
  2499.         /* We didn't get a file, no need to keep the
  2500.          * file requester.
  2501.          */
  2502.  
  2503.     if(!Result && AslFileRequest)
  2504.     {
  2505.         FreeAslRequest(AslFileRequest);
  2506.  
  2507.         return(NULL);
  2508.     }
  2509.     else
  2510.     {
  2511.         if(SaveFlag && AskWrite)
  2512.         {
  2513.             if(GetFileSize(Buffer))
  2514.             {
  2515.                 if(!MyEasyRequest(Parent,LocaleString(MSG_GLOBAL_FILE_ALREADY_EXISTS_OVERWRITE_TXT),LocaleString(MSG_GLOBAL_REPLACE_CANCEL_TXT),FilePart(Buffer)))
  2516.                 {
  2517.                     FreeAslRequest(AslFileRequest);
  2518.  
  2519.                     return(NULL);
  2520.                 }
  2521.             }
  2522.         }
  2523.  
  2524.         Forbid();
  2525.  
  2526.         if(DefaultPattern)
  2527.             strcpy(PatternBuffer,AslFileRequest -> rf_Pat);
  2528.  
  2529.         Permit();
  2530.  
  2531.         return(AslFileRequest);
  2532.     }
  2533. }
  2534.  
  2535.     /* MyEasyRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...):
  2536.      *
  2537.      *    Really quite simple varargs version of Intuition's
  2538.      *    EasyRequest requester.
  2539.      */
  2540.  
  2541. WORD __stdargs
  2542. MyEasyRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...)
  2543. {
  2544.     struct EasyStruct    Easy;
  2545.     WORD            Result;
  2546.     va_list             VarArgs;
  2547.  
  2548.         /* Standard data. */
  2549.  
  2550.     Easy . es_StructSize    = sizeof(struct EasyStruct);
  2551.     Easy . es_Flags        = NULL;
  2552.     Easy . es_Title        = LocaleString(MSG_TERMAUX_TERM_REQUEST_TXT);
  2553.     Easy . es_TextFormat    = Text;
  2554.     Easy . es_GadgetFormat    = Gadgets;
  2555.  
  2556.         /* Use the argument array to build the
  2557.          * requester and display it.
  2558.          */
  2559.  
  2560.     va_start(VarArgs,Gadgets);
  2561.     Result = EasyRequestArgs(Window,&Easy,NULL,VarArgs);
  2562.     va_end(VarArgs);
  2563.  
  2564.     return(Result);
  2565. }
  2566.  
  2567.     /* CloseWindowSafely(struct Window *Window):
  2568.      *
  2569.      *    Close a window freeing all messages pending at
  2570.      *    its user port (taken from example source code
  2571.      *    published once upon a time in Amiga Mail).
  2572.      */
  2573.  
  2574. VOID __regargs
  2575. CloseWindowSafely(struct Window *Window)
  2576. {
  2577.     struct IntuiMessage    *IntuiMessage;
  2578.     struct Node        *Successor;
  2579.  
  2580.     Forbid();
  2581.  
  2582.     IntuiMessage = (struct IntuiMessage *)Window -> UserPort -> mp_MsgList . lh_Head;
  2583.  
  2584.     while(Successor = IntuiMessage -> ExecMessage . mn_Node . ln_Succ)
  2585.     {
  2586.         if(IntuiMessage -> IDCMPWindow == Window)
  2587.         {
  2588.             Remove(IntuiMessage);
  2589.  
  2590.             ReplyMsg((struct Message *)IntuiMessage);
  2591.         }
  2592.  
  2593.         IntuiMessage = (struct IntuiMessage *)Successor;
  2594.     }
  2595.  
  2596.     Window -> UserPort = NULL;
  2597.  
  2598.     ModifyIDCMP(Window,NULL);
  2599.  
  2600.     Permit();
  2601.  
  2602.     LT_DeleteWindowLock(Window);
  2603.  
  2604.     CloseWindow(Window);
  2605. }
  2606.  
  2607.     /* WaitTime(LONG Secs,LONG Micros):
  2608.      *
  2609.      *    Wait a given period of time.
  2610.      */
  2611.  
  2612. VOID __regargs
  2613. WaitTime(LONG Secs,LONG Micros)
  2614. {
  2615.     TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  2616.     TimeRequest -> tr_time . tv_secs    = Secs;
  2617.     TimeRequest -> tr_time . tv_micro    = Micros;
  2618.  
  2619.     DoIO(TimeRequest);
  2620. }
  2621.  
  2622.     /* StopTime():
  2623.      *
  2624.      *    Stop the running timer.
  2625.      */
  2626.  
  2627. VOID
  2628. StopTime()
  2629. {
  2630.     if(TimerRunning)
  2631.     {
  2632.         if(!CheckIO(TimeRequest))
  2633.             AbortIO(TimeRequest);
  2634.  
  2635.         WaitIO(TimeRequest);
  2636.     }
  2637. }
  2638.  
  2639.     /* StartTime(LONG Secs,LONG Micros):
  2640.      *
  2641.      *    Start the timer asynchronously.
  2642.      */
  2643.  
  2644. VOID __regargs
  2645. StartTime(LONG Secs,LONG Micros)
  2646. {
  2647.     StopTime();
  2648.  
  2649.     TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  2650.     TimeRequest -> tr_time . tv_secs    = Secs;
  2651.     TimeRequest -> tr_time . tv_micro    = Micros;
  2652.  
  2653.     ClrSignal(SIG_TIMER);
  2654.  
  2655.     SendIO(TimeRequest);
  2656.  
  2657.     TimerRunning = TRUE;
  2658. }
  2659.  
  2660.     /* GetEnvDOS(STRPTR Name,STRPTR Buffer):
  2661.      *
  2662.      *    Get the contents of a vanilla AmigaDOS environment
  2663.      *    variable.
  2664.      */
  2665.  
  2666. STRPTR __regargs
  2667. GetEnvDOS(STRPTR Name,STRPTR Buffer)
  2668. {
  2669.     LONG    Size;
  2670.     BPTR    File,SomeLock;
  2671.  
  2672.     Buffer[0] = 0;
  2673.  
  2674.         /* Is ENV: present? */
  2675.  
  2676.     if(SomeLock = Lock("Env:",ACCESS_READ))
  2677.     {
  2678.         UBYTE SomeBuffer[MAX_FILENAME_LENGTH];
  2679.  
  2680.         UnLock(SomeLock);
  2681.  
  2682.         strcpy(SomeBuffer,"Env:");
  2683.         strcat(SomeBuffer,Name);
  2684.  
  2685.             /* Open the file. */
  2686.  
  2687.         if(File = Open(SomeBuffer,MODE_OLDFILE))
  2688.         {
  2689.                 /* Read the contents. */
  2690.  
  2691.             Size = Read(File,Buffer,256);
  2692.  
  2693.             Close(File);
  2694.  
  2695.             if(Size > 0)
  2696.             {
  2697.                 Buffer[Size] = 0;
  2698.  
  2699.                 return(Buffer);
  2700.             }
  2701.         }
  2702.     }
  2703.  
  2704.     return(NULL);
  2705. }
  2706.  
  2707.     /* SetEnvDOS(STRPTR Name,STRPTR Value):
  2708.      *
  2709.      *    Set the contents of a vanilla AmigaDOS environment
  2710.      *    variable.
  2711.      */
  2712.  
  2713. BYTE __regargs
  2714. SetEnvDOS(STRPTR Name,STRPTR Value)
  2715. {
  2716.     UBYTE    Buffer[MAX_FILENAME_LENGTH],*Destination;
  2717.     LONG    Length;
  2718.     BPTR    File,FileLock;
  2719.     BYTE    Success = TRUE;
  2720.     WORD    i;
  2721.  
  2722.     for(i = 0 ; i < 2 ; i++)
  2723.     {
  2724.         if(i)
  2725.             Destination = "EnvArc:";
  2726.         else
  2727.             Destination = "Env:";
  2728.  
  2729.             /* Is ENV:/ENVARC: present? */
  2730.  
  2731.         if(FileLock = Lock(Destination,ACCESS_READ))
  2732.         {
  2733.             UnLock(FileLock);
  2734.  
  2735.             strcpy(Buffer,Destination);
  2736.             strcat(Buffer,Name);
  2737.  
  2738.                 /* There already is a variable of that
  2739.                  * name in the environment storage
  2740.                  * directory.
  2741.                  */
  2742.  
  2743.             if(FileLock = Lock(Buffer,ACCESS_WRITE))
  2744.             {
  2745.                 UnLock(FileLock);
  2746.  
  2747.                     /* Delete the variable. */
  2748.  
  2749.                 if(!DeleteFile(Buffer))
  2750.                 {
  2751.                     Success = FALSE;
  2752.  
  2753.                     continue;
  2754.                 }
  2755.             }
  2756.  
  2757.                 /* Set the new variable. */
  2758.  
  2759.             if(Length = strlen(Value))
  2760.             {
  2761.                 if(File = Open(Buffer,MODE_NEWFILE))
  2762.                 {
  2763.                     if(Write(File,Value,Length) != Length)
  2764.                     {
  2765.                         Close(File);
  2766.  
  2767.                         DeleteFile(Buffer);
  2768.  
  2769.                         Success = FALSE;
  2770.                     }
  2771.                     else
  2772.                     {
  2773.                         Close(File);
  2774.  
  2775.                         AddProtection(Buffer,FIBF_EXECUTE);
  2776.                     }
  2777.                 }
  2778.                 else
  2779.                     Success = FALSE;
  2780.             }
  2781.         }
  2782.         else
  2783.             Success = FALSE;
  2784.     }
  2785.  
  2786.     return(Success);
  2787. }
  2788.  
  2789.     /* BumpWindow(struct Window *SomeWindow):
  2790.      *
  2791.      *    Bring a window to the front (and shift the screen
  2792.      *    back to its initial position).
  2793.      */
  2794.  
  2795. VOID __regargs
  2796. BumpWindow(struct Window *SomeWindow)
  2797. {
  2798.     if(SomeWindow)
  2799.     {
  2800.         if(SomeWindow -> WScreen -> LeftEdge > 0)
  2801.         {
  2802.             if(SomeWindow -> WScreen -> TopEdge > 0)
  2803.                 MoveScreen(SomeWindow -> WScreen,-SomeWindow -> WScreen -> LeftEdge,-SomeWindow -> WScreen -> TopEdge);
  2804.             else
  2805.                 MoveScreen(SomeWindow -> WScreen,-SomeWindow -> WScreen -> LeftEdge,0);
  2806.         }
  2807.         else
  2808.         {
  2809.             if(SomeWindow -> WScreen -> TopEdge > 0)
  2810.                 MoveScreen(SomeWindow -> WScreen,0,-SomeWindow -> WScreen -> TopEdge);
  2811.         }
  2812.  
  2813.         ScreenToFront(SomeWindow -> WScreen);
  2814.  
  2815.         ActivateWindow(SomeWindow);
  2816.     }
  2817. }
  2818.  
  2819.     /* PushWindow(struct Window *Window):
  2820.      *
  2821.      *    Push/PopWindow implement a single lifo window stack
  2822.      *    which always updates the window to activate when
  2823.      *    LSHIFT+RSHIFT+RETURN is pressed. This routine will
  2824.      *    push a window on the stack.
  2825.      */
  2826.  
  2827. VOID __regargs
  2828. PushWindow(struct Window *Window)
  2829. {
  2830.     if(WindowStackPtr < 5)
  2831.     {
  2832.         WindowStack[WindowStackPtr++] = Window;
  2833.  
  2834.         TopWindow = Window;
  2835.     }
  2836. }
  2837.  
  2838.     /* PopWindow():
  2839.      *
  2840.      *    Remove topmost window from window stack.
  2841.      */
  2842.  
  2843. VOID
  2844. PopWindow()
  2845. {
  2846.     if(WindowStackPtr > 0)
  2847.     {
  2848.         WindowStackPtr--;
  2849.  
  2850.         if(WindowStackPtr)
  2851.             TopWindow = WindowStack[WindowStackPtr - 1];
  2852.         else
  2853.             TopWindow = Window;
  2854.     }
  2855. }
  2856.  
  2857.     /* LoadMacros(STRPTR Name,struct MacroKeys *Keys):
  2858.      *
  2859.      *    Load the keyboard macros from a file.
  2860.      */
  2861.  
  2862. BYTE __regargs
  2863. LoadMacros(STRPTR Name,struct MacroKeys *Keys)
  2864. {
  2865.     struct IFFHandle    *Handle;
  2866.     BYTE             Success = FALSE;
  2867.     struct StoredProperty    *Prop;
  2868.     struct TermInfo        *TermInfo;
  2869.     LONG             Error;
  2870.  
  2871.     if(Handle = AllocIFF())
  2872.     {
  2873.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  2874.         {
  2875.             InitIFFasDOS(Handle);
  2876.  
  2877.             if(!(Error = OpenIFF(Handle,IFFF_READ)))
  2878.             {
  2879.                 /* Collect version number ID if
  2880.                  * available.
  2881.                  */
  2882.  
  2883.                 if(!(Error = PropChunks(Handle,(LONG *)VersionProps,1)))
  2884.                 {
  2885.                     /* The following line tells iffparse to stop at the
  2886.                      * very beginning of a `Type' chunk contained in a
  2887.                      * `TERM' FORM chunk.
  2888.                      */
  2889.  
  2890.                     if(!(Error = StopChunk(Handle,ID_TERM,ID_KEYS)))
  2891.                     {
  2892.                         /* Parse the file... */
  2893.  
  2894.                         if(!ParseIFF(Handle,IFFPARSE_SCAN))
  2895.                         {
  2896.                             /* Did we get a version ID? */
  2897.  
  2898.                             if(Prop = FindProp(Handle,ID_TERM,ID_VERS))
  2899.                             {
  2900.                                 TermInfo = (struct TermInfo *)Prop -> sp_Data;
  2901.  
  2902.                                 /* Is it the file format we are able
  2903.                                  * to read?
  2904.                                  */
  2905.  
  2906.                                 if((TermInfo -> Version > TermVersion) || (TermInfo -> Version == TermVersion && TermInfo -> Revision > TermRevision) || (TermInfo -> Version == 1 && TermInfo -> Revision < 6))
  2907.                                 {
  2908.                                         /* Probably an older revision. */
  2909.  
  2910.                                     if(TermInfo -> Version == 1 && TermInfo -> Revision < 6)
  2911.                                     {
  2912.                                         memset(Keys,0,sizeof(struct MacroKeys));
  2913.  
  2914.                                         if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
  2915.                                             Success = TRUE;
  2916.                                         else
  2917.                                             Error = IoErr();
  2918.                                     }
  2919.                                     else
  2920.                                         Error = ERR_OUTDATED;
  2921.                                 }
  2922.                                 else
  2923.                                 {
  2924.                                     /* The file read pointer is positioned
  2925.                                      * just in front of the first data
  2926.                                      * to be read, so let's don't disappoint
  2927.                                      * iffparse and read it.
  2928.                                      */
  2929.  
  2930.                                     if(ReadChunkBytes(Handle,Keys,sizeof(struct MacroKeys)) == sizeof(struct MacroKeys))
  2931.                                         Success = TRUE;
  2932.                                     else
  2933.                                         Error = IoErr();
  2934.                                 }
  2935.                             }
  2936.                             else
  2937.                             {
  2938.                                     /* File was created by WriteIFFData previous
  2939.                                      * to revision 1.4.
  2940.                                      */
  2941.  
  2942.                                 memset(Keys,0,sizeof(struct MacroKeys));
  2943.  
  2944.                                 if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
  2945.                                     Success = TRUE;
  2946.                                 else
  2947.                                     Error = IoErr();
  2948.                             }
  2949.                         }
  2950.                     }
  2951.                 }
  2952.  
  2953.                 CloseIFF(Handle);
  2954.             }
  2955.  
  2956.             Close(Handle -> iff_Stream);
  2957.         }
  2958.         else
  2959.             Error = IoErr();
  2960.  
  2961.         FreeIFF(Handle);
  2962.     }
  2963.     else
  2964.         Error = ERR_NO_MEM;
  2965.  
  2966.     if(Error)
  2967.         SetIoErr(Error);
  2968.  
  2969.     return(Success);
  2970. }
  2971.  
  2972.     /* WriteIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type):
  2973.      *
  2974.      *    Write data to an IFF file (via iffparse.library).
  2975.      */
  2976.  
  2977. BYTE __regargs
  2978. WriteIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type)
  2979. {
  2980.     struct IFFHandle    *Handle;
  2981.     BYTE             Success = FALSE;
  2982.     LONG             Error;
  2983.  
  2984.         /* Allocate a handle. */
  2985.  
  2986.     if(Handle = AllocIFF())
  2987.     {
  2988.             /* Open an output stream. */
  2989.  
  2990.         if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
  2991.         {
  2992.                 /* Tell iffparse that this is
  2993.                  * a DOS handle.
  2994.                  */
  2995.  
  2996.             InitIFFasDOS(Handle);
  2997.  
  2998.                 /* Open the handle for writing. */
  2999.  
  3000.             if(!(Error = OpenIFF(Handle,IFFF_WRITE)))
  3001.             {
  3002.                     /* Push outmost chunk onto stack. */
  3003.  
  3004.                 if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
  3005.                 {
  3006.                         /* Add a version identifier. */
  3007.  
  3008.                     if(!(Error = PushChunk(Handle,0,ID_VERS,IFFSIZE_UNKNOWN)))
  3009.                     {
  3010.                         struct TermInfo TermInfo;
  3011.  
  3012.                         TermInfo . Version    = TermVersion;
  3013.                         TermInfo . Revision    = TermRevision;
  3014.  
  3015.                             /* Write the version data. */
  3016.  
  3017.                         if(WriteChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
  3018.                         {
  3019.                                 /* Pop the version chunk, i.e. write it to the file. */
  3020.  
  3021.                             if(Error = PopChunk(Handle))
  3022.                                 Success = FALSE;
  3023.                             else
  3024.                             {
  3025.                                     /* Push the real data chunk on the stack. */
  3026.  
  3027.                                 if(!(Error = PushChunk(Handle,0,Type,IFFSIZE_UNKNOWN)))
  3028.                                 {
  3029.                                         /* Write the data. */
  3030.  
  3031.                                     if(WriteChunkBytes(Handle,Data,Size) == Size)
  3032.                                         Success = TRUE;
  3033.                                     else
  3034.                                         Error = IoErr();
  3035.  
  3036.                                             /* Pop the data chunk. */
  3037.  
  3038.                                     if(Success)
  3039.                                     {
  3040.                                         if(Error = PopChunk(Handle))
  3041.                                             Success = FALSE;
  3042.                                     }
  3043.                                 }
  3044.                                 else
  3045.                                     Success = FALSE;
  3046.                             }
  3047.                         }
  3048.                         else
  3049.                         {
  3050.                             Error = IoErr();
  3051.  
  3052.                             Success = FALSE;
  3053.                         }
  3054.                     }
  3055.  
  3056.                         /* Seems that we're done, now try to pop the FORM chunk
  3057.                          * and return.
  3058.                          */
  3059.  
  3060.                     if(Success)
  3061.                     {
  3062.                         if(Error = PopChunk(Handle))
  3063.                             Success = FALSE;
  3064.                     }
  3065.                 }
  3066.  
  3067.                     /* Close the handle (flush any pending data). */
  3068.  
  3069.                 CloseIFF(Handle);
  3070.             }
  3071.  
  3072.                 /* Close the DOS handle itself. */
  3073.  
  3074.             Close(Handle -> iff_Stream);
  3075.         }
  3076.         else
  3077.             Error = IoErr();
  3078.  
  3079.             /* And free the IFF handle. */
  3080.  
  3081.         FreeIFF(Handle);
  3082.     }
  3083.     else
  3084.         Error = ERR_NO_MEM;
  3085.  
  3086.     if(Success)
  3087.         AddProtection(Name,FIBF_EXECUTE);
  3088.  
  3089.     if(Error)
  3090.         SetIoErr(Error);
  3091.  
  3092.     return(Success);
  3093. }
  3094.  
  3095.     /* ReadIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type):
  3096.      *
  3097.      *    Read data from a `TERM' FORM chunk contained in an IFF file.
  3098.      */
  3099.  
  3100. BYTE __regargs
  3101. ReadIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type)
  3102. {
  3103.     struct IFFHandle    *Handle;
  3104.     BYTE             Success = FALSE;
  3105.     struct StoredProperty    *Prop;
  3106.     struct TermInfo        *TermInfo;
  3107.     LONG             Error = 0;
  3108.  
  3109.     if(Handle = AllocIFF())
  3110.     {
  3111.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  3112.         {
  3113.             InitIFFasDOS(Handle);
  3114.  
  3115.             if(!(Error = OpenIFF(Handle,IFFF_READ)))
  3116.             {
  3117.                 /* Collect version number ID if
  3118.                  * available.
  3119.                  */
  3120.  
  3121.                 if(!(Error = PropChunks(Handle,(LONG *)VersionProps,1)))
  3122.                 {
  3123.                     /* The following line tells iffparse to stop at the
  3124.                      * very beginning of a `Type' chunk contained in a
  3125.                      * `TERM' FORM chunk.
  3126.                      */
  3127.  
  3128.                     if(!(Error = StopChunk(Handle,ID_TERM,Type)))
  3129.                     {
  3130.                         /* Parse the file... */
  3131.  
  3132.                         if(!ParseIFF(Handle,IFFPARSE_SCAN))
  3133.                         {
  3134.                             /* Did we get a version ID? */
  3135.  
  3136.                             if(Prop = FindProp(Handle,ID_TERM,ID_VERS))
  3137.                             {
  3138.                                 TermInfo = (struct TermInfo *)Prop -> sp_Data;
  3139.  
  3140.                                 /* Is it the file format we are able
  3141.                                  * to read?
  3142.                                  */
  3143.  
  3144.                                 if((TermInfo -> Version > TermVersion) || (TermInfo -> Version == TermVersion && TermInfo -> Revision > TermRevision) || (TermInfo -> Version == 1 && TermInfo -> Revision < 6))
  3145.                                 {
  3146.                                     Error = ERR_OUTDATED;
  3147.  
  3148.                                     Success = FALSE;
  3149.                                 }
  3150.                                 else
  3151.                                 {
  3152.                                     struct ContextNode *Chunk = CurrentChunk(Handle);
  3153.  
  3154.                                     if(Chunk -> cn_Size < Size)
  3155.                                         Size = Chunk -> cn_Size;
  3156.  
  3157.                                     /* The file read pointer is positioned
  3158.                                      * just in front of the first data
  3159.                                      * to be read, so let's don't disappoint
  3160.                                      * iffparse and read it.
  3161.                                      */
  3162.  
  3163.                                     if(ReadChunkBytes(Handle,Data,Size) == Size)
  3164.                                         Success = TRUE;
  3165.                                     else
  3166.                                         Error = IoErr();
  3167.                                 }
  3168.                             }
  3169.                         }
  3170.                     }
  3171.                 }
  3172.  
  3173.                 CloseIFF(Handle);
  3174.             }
  3175.  
  3176.             Close(Handle -> iff_Stream);
  3177.         }
  3178.         else
  3179.             Error = IoErr();
  3180.  
  3181.         FreeIFF(Handle);
  3182.     }
  3183.  
  3184.     if(Error)
  3185.         SetIoErr(Error);
  3186.  
  3187.     return(Success);
  3188. }
  3189.  
  3190.     /* SplitFileName():
  3191.      *
  3192.      *    Split a full file name into a file and a drawer name.
  3193.      */
  3194.  
  3195. VOID __regargs
  3196. SplitFileName(STRPTR FullName,STRPTR *FileName,STRPTR DrawerName)
  3197. {
  3198.     if(FilePart(FullName) == FullName)
  3199.     {
  3200.         *DrawerName    = 0;
  3201.         *FileName    = FullName;
  3202.     }
  3203.     else
  3204.     {
  3205.         STRPTR Dummy;
  3206.  
  3207.         strcpy(DrawerName,FullName);
  3208.  
  3209.         Dummy = PathPart(DrawerName);
  3210.  
  3211.         *Dummy = 0;
  3212.  
  3213.         *FileName = FilePart(FullName);
  3214.     }
  3215. }
  3216.  
  3217.     /* CreateList():
  3218.      *
  3219.      *    Create a small, empty list.
  3220.      */
  3221.  
  3222. struct List *
  3223. CreateList()
  3224. {
  3225.     struct List *List = (struct List *)AllocVecPooled(sizeof(struct MinList),MEMF_ANY);
  3226.  
  3227.     if(List)
  3228.         NewList(List);
  3229.  
  3230.     return(List);
  3231. }
  3232.  
  3233.     /* DeleteList():
  3234.      *
  3235.      *    Free the contents of a list and the list itself.
  3236.      */
  3237.  
  3238. VOID __regargs
  3239. DeleteList(struct List *List)
  3240. {
  3241.     if(List)
  3242.     {
  3243.         struct Node    *Node,
  3244.                 *Next;
  3245.  
  3246.         for(Node = List -> lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  3247.             FreeVecPooled(Node);
  3248.  
  3249.         FreeVecPooled(List);
  3250.     }
  3251. }
  3252.  
  3253.     /* BackfillRoutine():
  3254.      *
  3255.      *    Window layer backfill routine.
  3256.      */
  3257.  
  3258. ULONG __asm __saveds
  3259. BackfillRoutine(register __a0 struct Hook *Hook,register __a1 struct {ULONG Layer; struct Rectangle Bounds;} *Bounds,register __a2 struct RastPort *RPort)
  3260. {
  3261.     struct RastPort RastPort = *RPort;
  3262.  
  3263.     RPort = &RastPort;
  3264.  
  3265.     RPort -> Layer = NULL;
  3266.  
  3267.     SetAPen(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
  3268.     SetDrMd(RPort,JAM1);
  3269.  
  3270.     RectFill(RPort,Bounds -> Bounds . MinX,Bounds -> Bounds . MinY,Bounds -> Bounds . MaxX,Bounds -> Bounds . MaxY);
  3271.  
  3272.     return(TRUE);
  3273. }
  3274.  
  3275. struct NameSegment
  3276. {
  3277.     UBYTE    String[63],
  3278.         Separator;
  3279. };
  3280.  
  3281. STATIC UBYTE * __regargs
  3282. GetNameSegment(struct NameSegment *NameSegment,UBYTE *cp,WORD i)
  3283. {
  3284.     UBYTE *xp = NameSegment[i] . String;
  3285.  
  3286.     while (*cp && !strchr("._+-,@~=",*cp))
  3287.         *xp++ = *cp++;
  3288.  
  3289.     *xp = '\0';
  3290.  
  3291.     NameSegment[i] . Separator = *cp;
  3292.  
  3293.     if (*cp)
  3294.         cp++;
  3295.  
  3296.     if(NameSegment[i] . String[0] || NameSegment[i] . Separator)
  3297.         return(cp);
  3298.     else
  3299.         return(NULL);
  3300. }
  3301.  
  3302. STATIC VOID __regargs
  3303. CopyNameSegment(struct NameSegment *NameSegment,UBYTE *Destination,WORD Zap)
  3304. {
  3305.     UBYTE *cp = Destination,*xp;
  3306.  
  3307.     for(xp = NameSegment[0] . String ; *xp ; )
  3308.         *cp++ = *xp++;
  3309.  
  3310.     if(NameSegment[0] . Separator)
  3311.     {
  3312.         register WORD i;
  3313.  
  3314.         *cp++ = NameSegment[0] . Separator;
  3315.  
  3316.         for(i = Zap + 1 ; ; i++)
  3317.         {
  3318.             for(xp = NameSegment[i] . String ; *xp ; )
  3319.                 *cp++ = *xp++;
  3320.  
  3321.             if(NameSegment[i] . Separator)
  3322.                 *cp++ = NameSegment[i] . Separator;
  3323.             else
  3324.             {
  3325.                 if(!NameSegment[i] . String[0])
  3326.                     break;
  3327.             }
  3328.         }
  3329.     }
  3330.  
  3331.     *cp = 0;
  3332. }
  3333.  
  3334.     /* ShrinkName():
  3335.      *
  3336.      *    Shrink a file name down to a number of characters, if
  3337.      *    possible preserving the structure of the name. Algorithm
  3338.      *    courtesy of the "shrink" program by Simon Brown,
  3339.      *    Edinburgh University.
  3340.      */
  3341.  
  3342. UBYTE * __regargs
  3343. ShrinkName(const UBYTE *Source,UBYTE *Destination,WORD MaxLength,BOOLEAN FixSuffix)
  3344. {
  3345.     #define MAXSEGS 10
  3346.  
  3347.     struct NameSegment NameSegment[MAXSEGS];
  3348.  
  3349.     WORD i,NumSegments,SuffixLength,Remainder,Delete,Total,Zap = 0;
  3350.     UBYTE *OldPtr = (UBYTE *)Source;
  3351.  
  3352.     for(i = 0 ; i < MAXSEGS && (OldPtr = GetNameSegment(NameSegment,OldPtr,i)) ; i++);
  3353.  
  3354.     if(i < MAXSEGS)
  3355.     {
  3356.         NumSegments = i - 1;
  3357.  
  3358.         if((NumSegments * 2) < MaxLength)
  3359.         {
  3360.             SuffixLength = strlen(NameSegment[NumSegments] . String);
  3361.  
  3362.             if(SuffixLength > MaxLength - NumSegments - 1)
  3363.             {
  3364.                 SuffixLength = MaxLength - (2 * NumSegments) - 1;
  3365.  
  3366.                 NameSegment[NumSegments] . String[SuffixLength - 1] = 0;
  3367.             }
  3368.             else
  3369.             {
  3370.                 if (SuffixLength + NumSegments > MaxLength-NumSegments-1)
  3371.                     Zap = NumSegments - (MaxLength-SuffixLength)/2;
  3372.             }
  3373.  
  3374.             if(NumSegments >= 1)
  3375.             {
  3376.                 for(i = Zap + 1 ; i <= NumSegments ; i++)
  3377.                 {
  3378.                     if(NameSegment[i] . Separator)
  3379.                         SuffixLength++;
  3380.                 }
  3381.  
  3382.                 if(NameSegment[0] . Separator)
  3383.                     SuffixLength++;
  3384.  
  3385.                 Remainder = MaxLength - SuffixLength;
  3386.  
  3387.                 Delete = Remainder / NumSegments;
  3388.  
  3389.                 Total = SuffixLength;
  3390.  
  3391.                 for(i = Zap + 1 ; i < NumSegments ; i++)
  3392.                 {
  3393.                     NameSegment[i] . String[Delete] = 0;
  3394.  
  3395.                     Total += Delete;
  3396.                 }
  3397.  
  3398.                 NameSegment[0] . String[MaxLength - Total] = 0;
  3399.             }
  3400.  
  3401.             CopyNameSegment(NameSegment,Destination,Zap);
  3402.         }
  3403.         else
  3404.             strcpy(Destination,Source);
  3405.     }
  3406.     else
  3407.         strcpy(Destination,Source);
  3408.  
  3409.     if(FixSuffix)
  3410.     {
  3411.         BOOLEAN    GotDot    = FALSE;
  3412.         LONG    Len    = strlen(Destination),Dots;
  3413.  
  3414.         for(i = Dots = 0 ; i < Len ; i++)
  3415.         {
  3416.             if(Destination[i] == '.')
  3417.                 Dots++;
  3418.         }
  3419.  
  3420.         if(!Dots)
  3421.         {
  3422.             if(Len < 4)
  3423.                 strcat(Destination,".___");
  3424.             else
  3425.                 Destination[Len - 4] = '.';
  3426.         }
  3427.  
  3428.         for(i = Len - 1 ; i >= 0 ; i--)
  3429.         {
  3430.             if(Destination[i] == '.')
  3431.             {
  3432.                 if(GotDot)
  3433.                     Destination[i] = '_';
  3434.                 else
  3435.                     GotDot = TRUE;
  3436.             }
  3437.  
  3438.             if(Destination[i] == '\\')
  3439.                 Destination[i] = '-';
  3440.         }
  3441.     }
  3442.  
  3443.     return(Destination);
  3444. }
  3445.  
  3446.     /* BuildFontName(STRPTR Destination,const STRPTR Name,LONG Size):
  3447.      *
  3448.      *    Build a font name and size string from given
  3449.      *    information (raw name and size).
  3450.      */
  3451.  
  3452. VOID __regargs
  3453. BuildFontName(STRPTR Destination,const STRPTR Name,LONG Size)
  3454. {
  3455.     UBYTE    LocalBuffer[50];
  3456.     LONG    Len;
  3457.  
  3458.     strcpy(LocalBuffer,FilePart((STRPTR)Name));
  3459.  
  3460.     Len = strlen(LocalBuffer);
  3461.  
  3462.     if(Len > 5)
  3463.     {
  3464.         if(!Stricmp(&LocalBuffer[Len - 5],".font"))
  3465.             LocalBuffer[Len - 5] = 0;
  3466.     }
  3467.  
  3468.     SPrintf(Destination,"%s %ld",LocalBuffer,Size);
  3469. }
  3470.  
  3471.     /* CreateMenuGlyphs():
  3472.      *
  3473.      *    Create scaled glyphs for pull-down menus.
  3474.      */
  3475.  
  3476. BOOLEAN __regargs
  3477. CreateMenuGlyphs(struct Screen *Screen,struct DrawInfo *DrawInfo,struct Image **AmigaPtr,struct Image **CheckPtr)
  3478. {
  3479.     struct Image    *AmigaGlyph,
  3480.             *CheckGlyph;
  3481.     LONG         AspectX,AspectY,
  3482.              Size,FontHeight;
  3483.  
  3484.     FontHeight = DrawInfo -> dri_Font -> tf_Baseline + 2;
  3485.  
  3486.     if(Screen -> Flags & SCREENHIRES)
  3487.         Size = SYSISIZE_MEDRES;
  3488.     else
  3489.         Size = SYSISIZE_LOWRES;
  3490.  
  3491.     AspectX = DrawInfo -> dri_Resolution . X;
  3492.     AspectY = DrawInfo -> dri_Resolution . Y;
  3493.  
  3494.     if(AmigaGlyph = NewObject(NULL,SYSICLASS,
  3495.         SYSIA_DrawInfo,    DrawInfo,
  3496.         SYSIA_Size,    Size,
  3497.         SYSIA_Which,    AMIGAKEY,
  3498.         IA_Left,    0,
  3499.         LA_Top,        0,
  3500.         IA_Width,    (FontHeight * 3 * AspectY) / (2 * AspectX),
  3501.         IA_Height,    FontHeight,
  3502.     TAG_DONE))
  3503.     {
  3504.         if(!(CheckGlyph = NewObject(NULL,SYSICLASS,
  3505.             SYSIA_DrawInfo,    DrawInfo,
  3506.             SYSIA_Size,    Size,
  3507.             SYSIA_Which,    MENUCHECK,
  3508.             IA_Left,    0,
  3509.             LA_Top,        0,
  3510.             IA_Width,    (FontHeight * AspectY) / AspectX,
  3511.             IA_Height,    FontHeight,
  3512.         TAG_DONE)))
  3513.         {
  3514.             DisposeObject(AmigaGlyph);
  3515.  
  3516.             AmigaGlyph = NULL;
  3517.         }
  3518.     }
  3519.  
  3520.     if(AmigaGlyph && CheckGlyph)
  3521.     {
  3522.         *AmigaPtr = AmigaGlyph;
  3523.         *CheckPtr = CheckGlyph;
  3524.  
  3525.         return(TRUE);
  3526.     }
  3527.     else
  3528.         return(FALSE);
  3529. }
  3530.  
  3531.     /* FixName(STRPTR Name):
  3532.      *
  3533.      *    Build a correct AmigaDOS filename.
  3534.      */
  3535.  
  3536. VOID __regargs
  3537. FixName(STRPTR Name)
  3538. {
  3539.     WORD    NameLen    = strlen(Name),
  3540.         i;
  3541.  
  3542.         /* Replace special characters. */
  3543.  
  3544.     for(i = 0 ; i < NameLen ; i++)
  3545.     {
  3546.         switch(Name[i])
  3547.         {
  3548.             case ' ':
  3549.  
  3550.                 Name[i] = '_';
  3551.                 break;
  3552.  
  3553.             case ':':
  3554.  
  3555.                 Name[i] = '.';
  3556.                 break;
  3557.  
  3558.             case '/':
  3559.  
  3560.                 Name[i] = '\\';
  3561.                 break;
  3562.  
  3563.             case '\"':
  3564.  
  3565.                 Name[i] = '\'';
  3566.                 break;
  3567.         }
  3568.     }
  3569.  
  3570.         /* Truncate the name. */
  3571.  
  3572.     if(NameLen > 31)
  3573.         Name[31] = 0;
  3574. }
  3575.  
  3576.     /* ShowError(struct Window *Window,LONG Primary,LONG Secondary,STRPTR String):
  3577.      *
  3578.      *    Display an error message, in human readable form if possible.
  3579.      */
  3580.  
  3581. VOID __regargs
  3582. ShowError(struct Window *Window,LONG Primary,LONG Secondary,STRPTR String)
  3583. {
  3584.     STATIC LONG LocalErrors[][2] =
  3585.     {
  3586.         ERR_SAVE_ERROR,            MSG_ERR_COULD_NOT_SAVE_FILE_TXT,
  3587.         ERR_LOAD_ERROR,            MSG_ERR_COULD_NOT_LOAD_FILE_TXT,
  3588.         ERR_NO_MEM,            MSG_ERR_NO_MEM_TXT,
  3589.         ERR_OUTDATED,            MSG_ERR_OUTDATED_TXT,
  3590.  
  3591.         IFFERR_NOMEM,            MSG_IFFERR_NOMEM_TXT,
  3592.         IFFERR_READ,            MSG_IFFERR_READ_TXT,
  3593.         IFFERR_WRITE,            MSG_IFFERR_WRITE_TXT,
  3594.         IFFERR_SEEK,            MSG_IFFERR_SEEK_TXT,
  3595.         IFFERR_MANGLED,            MSG_IFFERR_MANGLED_TXT,
  3596.         IFFERR_NOTIFF,            MSG_IFFERR_NOTIFF_TXT,
  3597.  
  3598.         0,                0
  3599.     };
  3600.  
  3601.     STRPTR    PrimaryError    = NULL,
  3602.         SecondaryError    = NULL;
  3603.  
  3604.     if(Primary)
  3605.     {
  3606.         LONG i;
  3607.  
  3608.         for(i = 0 ; LocalErrors[i][0] ; i++)
  3609.         {
  3610.             if(LocalErrors[i][0] == Primary)
  3611.             {
  3612.                 PrimaryError = LocaleString(LocalErrors[i][1]);
  3613.  
  3614.                 break;
  3615.             }
  3616.         }
  3617.  
  3618.         if(!PrimaryError)
  3619.         {
  3620.             STATIC UBYTE __far Buffer[256];
  3621.  
  3622.             Fault(Primary,"",Buffer,256);
  3623.  
  3624.             PrimaryError = Buffer + 2;
  3625.         }
  3626.     }
  3627.  
  3628.     if(Secondary)
  3629.     {
  3630.         LONG i;
  3631.  
  3632.         for(i = 0 ; LocalErrors[i][0] ; i++)
  3633.         {
  3634.             if(LocalErrors[i][0] == Secondary)
  3635.             {
  3636.                 SecondaryError = LocaleString(LocalErrors[i][1]);
  3637.  
  3638.                 break;
  3639.             }
  3640.         }
  3641.  
  3642.         if(!SecondaryError)
  3643.         {
  3644.             STATIC UBYTE __far Buffer[256];
  3645.  
  3646.             Fault(Secondary,"",Buffer,256);
  3647.  
  3648.             SecondaryError = Buffer + 2;
  3649.         }
  3650.     }
  3651.  
  3652.     if(PrimaryError)
  3653.     {
  3654.         if(String)
  3655.             MyEasyRequest(Window,PrimaryError,LocaleString(MSG_GLOBAL_CONTINUE_TXT),String,SecondaryError);
  3656.         else
  3657.             MyEasyRequest(Window,PrimaryError,LocaleString(MSG_GLOBAL_CONTINUE_TXT),SecondaryError);
  3658.     }
  3659. }
  3660.  
  3661. struct RendezvousData * __saveds __asm
  3662. RendezvousLogin(register __a0 struct MsgPort *ReadPort,register __a1 struct MsgPort *WritePort,register __a2 struct TagItem *TagList)
  3663. {
  3664.     struct RendezvousData *Data;
  3665.  
  3666.     if(Data = (struct RendezvousData *)AllocVecPooled(sizeof(struct RendezvousData),MEMF_ANY | MEMF_CLEAR))
  3667.     {
  3668.         struct DataMsg Msg;
  3669.  
  3670.         InitMsgItem(&Msg,TaskDestructor);
  3671.  
  3672.         Msg . Type = DATAMSGTYPE_RENDEZVOUS;
  3673.         Msg . Data = (UBYTE *)SysBase -> ThisTask;
  3674.  
  3675.         Forbid();
  3676.  
  3677.         ClrSignal(SIGBREAKF_CTRL_F);
  3678.  
  3679.         PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  3680.  
  3681.         Wait(SIGBREAKF_CTRL_F);
  3682.  
  3683.         Permit();
  3684.  
  3685.         if(ReadRequest && WriteRequest)
  3686.         {
  3687.             struct List *UploadList;
  3688.  
  3689.             CopyMem(ReadRequest,&Data -> rd_ReadRequest,sizeof(struct IOExtSer));
  3690.  
  3691.             Data -> rd_ReadRequest . IOSer . io_Message . mn_ReplyPort = ReadPort;
  3692.  
  3693.             CopyMem(WriteRequest,&Data -> rd_WriteRequest,sizeof(struct IOExtSer));
  3694.  
  3695.             Data -> rd_WriteRequest . IOSer . io_Message . mn_ReplyPort = WritePort;
  3696.  
  3697.             if(Window)
  3698.                 Data -> rd_Screen = Window -> WScreen;
  3699.  
  3700.             NewList(&Data -> rd_UploadList);
  3701.             NewList(&Data -> rd_DownloadList);
  3702.             NewList(&Data -> rd_SentList);
  3703.             NewList(&Data -> rd_ReceivedList);
  3704.  
  3705.             if(UploadList = GetUploadList())
  3706.             {
  3707.                 struct Node *Node,*Next;
  3708.  
  3709.                 for(Node = UploadList -> lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  3710.                     AddTail(&Data -> rd_UploadList,Node);
  3711.  
  3712.                 FreeVecPooled(UploadList);
  3713.             }
  3714.  
  3715.             Data -> rd_SendPath    = Config -> PathConfig -> BinaryUploadPath;
  3716.             Data -> rd_ReceivePath    = Config -> PathConfig -> BinaryDownloadPath;
  3717.             Data -> rd_Options    = "";
  3718.         }
  3719.         else
  3720.         {
  3721.             FreeVecPooled(Data);
  3722.  
  3723.             Data = NULL;
  3724.         }
  3725.     }
  3726.  
  3727.     return(Data);
  3728. }
  3729.  
  3730. VOID __saveds __asm
  3731. RendezvousLogoff(register __a0 struct RendezvousData *Data)
  3732. {
  3733.     if(Data)
  3734.     {
  3735.         struct Node *Node,*Next;
  3736.  
  3737.         for(Node = Data -> rd_UploadList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  3738.             FreeVecPooled(Node);
  3739.  
  3740.         for(Node = Data -> rd_DownloadList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  3741.             FreeVecPooled(Node);
  3742.  
  3743.         for(Node = Data -> rd_SentList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  3744.             FreeVecPooled(Node);
  3745.  
  3746.         for(Node = Data -> rd_ReceivedList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  3747.             FreeVecPooled(Node);
  3748.  
  3749.         FreeVecPooled(Data);
  3750.  
  3751.         Signal(ThisProcess,SIG_HANDSHAKE);
  3752.     }
  3753. }
  3754.  
  3755. struct Node * __saveds __asm
  3756. RendezvousNewNode(register __a0 STRPTR Name)
  3757. {
  3758.     if(Name)
  3759.     {
  3760.         LONG Len;
  3761.  
  3762.         if(Len = strlen(Name))
  3763.         {
  3764.             struct Node *Node;
  3765.  
  3766.             if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + Len + 1,MEMF_ANY))
  3767.             {
  3768.                 memset(Node,0,sizeof(struct Node));
  3769.  
  3770.                 strcpy(Node -> ln_Name = (STRPTR)(Node + 1),Name);
  3771.  
  3772.                 return(Node);
  3773.             }
  3774.         }
  3775.     }
  3776.  
  3777.     return(NULL);
  3778. }
  3779.  
  3780. struct List * __regargs
  3781. BuildModeList(LONG *Index,ULONG DisplayMode,ULONG (* __asm ModeFilter)(register __a1 ULONG ID))
  3782. {
  3783.     struct List    *List;
  3784.     LONG         Count = 0;
  3785.  
  3786.     *Index = 0;
  3787.  
  3788.     if(List = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY))
  3789.     {
  3790.         struct DisplayInfo    DisplayInfo;
  3791.         ULONG            SomeMode = INVALID_ID;
  3792.  
  3793.         NewList(List);
  3794.  
  3795.         while((SomeMode = NextDisplayInfo(SomeMode)) != INVALID_ID)
  3796.         {
  3797.             if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,SomeMode))
  3798.             {
  3799.                 if((DisplayInfo . PropertyFlags & DIPF_IS_WB) && !DisplayInfo . NotAvailable)
  3800.                 {
  3801.                     STRPTR Name;
  3802.  
  3803.                     if(ModeFilter)
  3804.                     {
  3805.                         if(!(*ModeFilter)(SomeMode))
  3806.                             continue;
  3807.                     }
  3808.  
  3809.                     if(Name = GetModeName(SomeMode))
  3810.                     {
  3811.                         struct ModeNode    *ModeNode;
  3812.  
  3813.                         if(ModeNode = (struct ModeNode *)AllocVecPooled(sizeof(struct ModeNode) + strlen(Name) + 1,MEMF_ANY))
  3814.                         {
  3815.                             ModeNode -> VanillaNode . ln_Name = (STRPTR)(ModeNode + 1);
  3816.  
  3817.                             strcpy(ModeNode -> VanillaNode . ln_Name,Name);
  3818.  
  3819.                             ModeNode -> DisplayID = SomeMode;
  3820.  
  3821.                             AddTail(List,ModeNode);
  3822.  
  3823.                             Count++;
  3824.                         }
  3825.                     }
  3826.                 }
  3827.             }
  3828.         }
  3829.     }
  3830.  
  3831.     if(Count)
  3832.     {
  3833.         struct ModeNode    *Node,
  3834.                 *Next;
  3835.  
  3836.         for(Node = (struct ModeNode *)List -> lh_Head ; Node -> VanillaNode . ln_Succ ; Node = (struct ModeNode *)Node -> VanillaNode . ln_Succ)
  3837.         {
  3838.             if(!(Node -> DisplayID & MONITOR_ID_MASK))
  3839.             {
  3840.                 for(Next = (struct ModeNode *)List -> lh_Head ; Next -> VanillaNode . ln_Succ ; Next = (struct ModeNode *)Next -> VanillaNode . ln_Succ)
  3841.                 {
  3842.                     if((Node -> DisplayID & ~MONITOR_ID_MASK) == (Next -> DisplayID & ~MONITOR_ID_MASK) && Next != Node)
  3843.                         Node -> DisplayID = INVALID_ID;
  3844.                 }
  3845.             }
  3846.  
  3847.             for(Next = (struct ModeNode *)List -> lh_Head ; Next -> VanillaNode . ln_Succ ; Next = (struct ModeNode *)Next -> VanillaNode . ln_Succ)
  3848.             {
  3849.                 if(Node -> DisplayID == Next -> DisplayID && Next != Node)
  3850.                     Next -> DisplayID = INVALID_ID;
  3851.             }
  3852.         }
  3853.  
  3854.         for(Node = (struct ModeNode *)List -> lh_Head ; Next = (struct ModeNode *)Node -> VanillaNode . ln_Succ ; Node = Next)
  3855.         {
  3856.             if(Node -> DisplayID == INVALID_ID)
  3857.             {
  3858.                 Count--;
  3859.  
  3860.                 Remove(Node);
  3861.  
  3862.                 FreeVecPooled(Node);
  3863.             }
  3864.         }
  3865.     }
  3866.  
  3867.     if(Count)
  3868.     {
  3869.         struct ModeNode    *Node,
  3870.                 *Next;
  3871.  
  3872.         for(Count = 0, Node = (struct ModeNode *)List -> lh_Head ; Next = (struct ModeNode *)Node -> VanillaNode . ln_Succ ; Node = Next)
  3873.         {
  3874.             if(Node -> DisplayID == DisplayMode)
  3875.             {
  3876.                 *Index = Count;
  3877.  
  3878.                 break;
  3879.             }
  3880.         }
  3881.  
  3882.         return(List);
  3883.     }
  3884.     else
  3885.     {
  3886.         DeleteList(List);
  3887.  
  3888.         return(NULL);
  3889.     }
  3890. }
  3891.  
  3892.     /* IsAssign(STRPTR Name):
  3893.      *
  3894.      *    Does a name refer to an assignment?
  3895.      */
  3896.  
  3897. BOOLEAN __regargs
  3898. IsAssign(STRPTR Name)
  3899. {
  3900.     WORD NameLen    = strlen(Name) - 1;
  3901.     BOOLEAN Result    = FALSE;
  3902.  
  3903.         /* Does it end with a colon? */
  3904.  
  3905.     if(Name[NameLen] == ':')
  3906.     {
  3907.         struct DosList *DosList;
  3908.  
  3909.             /* Lock the list of assignments for reading. */
  3910.  
  3911.         DosList = AttemptLockDosList(LDF_ASSIGNS | LDF_READ);
  3912.  
  3913.             /* Make sure the v37 bug doesn't catch us. */
  3914.  
  3915.         if(((ULONG)DosList) > 1)
  3916.         {
  3917.             STRPTR AssignName;
  3918.  
  3919.                 /* Scan the list... */
  3920.  
  3921.             while(DosList = NextDosEntry(DosList,LDF_ASSIGNS))
  3922.             {
  3923.                     /* Convert the name from icky
  3924.                      * BCPL to `C' style string.
  3925.                      */
  3926.  
  3927.                 AssignName = (STRPTR)BADDR(DosList -> dol_Name);
  3928.  
  3929.                     /* Does the name length match? */
  3930.  
  3931.                 if(AssignName[0] == NameLen)
  3932.                 {
  3933.                         /* Does the name itself match? */
  3934.  
  3935.                     if(!Strnicmp(&AssignName[1],Name,NameLen))
  3936.                     {
  3937.                         Result = TRUE;
  3938.  
  3939.                         break;
  3940.                     }
  3941.                 }
  3942.             }
  3943.  
  3944.                 /* Unlock the list of assignments. */
  3945.  
  3946.             UnLockDosList(LDF_ASSIGNS | LDF_READ);
  3947.         }
  3948.     }
  3949.  
  3950.         /* Return the result. */
  3951.  
  3952.     return(Result);
  3953. }
  3954.  
  3955.     /* LockInAssign(BPTR TheLock,STRPTR TheAssignment):
  3956.      *
  3957.      *    Check if a file lock is part of an assignment.
  3958.      */
  3959.  
  3960. BOOLEAN __regargs
  3961. LockInAssign(BPTR TheLock,STRPTR TheAssignment)
  3962. {
  3963.     struct DevProc    *DevProc    = NULL;
  3964.     struct MsgPort    *FileSysTask    = GetFileSysTask();
  3965.     BOOLEAN         Result        = FALSE;
  3966.  
  3967.  
  3968.         /* Loop until all assignments are
  3969.          * processed.
  3970.          */
  3971.     
  3972.     do
  3973.     {
  3974.             /* Get the default filesystem task
  3975.              * in case we stumble upon NULL
  3976.              * directory locks.
  3977.              */
  3978.     
  3979.         if(DevProc = GetDeviceProc(TheAssignment,DevProc))
  3980.         {
  3981.                 /* Set the default filesystem task. */
  3982.     
  3983.             SetFileSysTask(DevProc -> dvp_Port);
  3984.     
  3985.                 /* Is the lock on the list? */
  3986.     
  3987.             if(SameLock(DevProc -> dvp_Lock,TheLock) == LOCK_SAME)
  3988.                 Result = TRUE;
  3989.         }
  3990.         else
  3991.             break;
  3992.     }
  3993.     while(DevProc && (DevProc -> dvp_Flags & DVPF_ASSIGN) && !Result);
  3994.     
  3995.         /* Reset the default filesystem task. */
  3996.     
  3997.     SetFileSysTask(FileSysTask);
  3998.     
  3999.         /* Free device process data. */
  4000.     
  4001.     if(DevProc)
  4002.         FreeDeviceProc(DevProc);
  4003.  
  4004.     return(Result);
  4005. }
  4006.